<!DOCTYPE html>
<html lang="zh-CN" dir="ltr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>7.7 对话框详解 | 落光的Pro博客</title>
    <meta name="description" content="Vite & Vue powered static site generator.">
    <link rel="preload stylesheet" href="./assets/style.4b0df91d.css" as="style">
    
    <script type="module" src="./assets/app.0acbd3fd.js"></script>
    <link rel="preload" href="./assets/inter-roman-latin.2ed14f66.woff2" as="font" type="font/woff2" crossorigin="">
    <link rel="modulepreload" href="./assets/chunks/framework.eaf25f5b.js">
    <link rel="modulepreload" href="./assets/chunks/theme.ce44a0e6.js">
    <link rel="modulepreload" href="./assets/largeFrontEnd_flutter_chapter7_dailog.md.5f91e51a.lean.js">
    <script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
  </head>
  <body>
    <div id="app"><div class="Layout" data-v-1919c326><!--[--><!--]--><!--[--><span tabindex="-1" data-v-0f60ec36></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-0f60ec36> Skip to content </a><!--]--><!----><header class="VPNav" data-v-1919c326 data-v-7e5bc4a5><div class="VPNavBar has-sidebar" data-v-7e5bc4a5 data-v-a0fd61f4><div class="container" data-v-a0fd61f4><div class="title" data-v-a0fd61f4><div class="VPNavBarTitle has-sidebar" data-v-a0fd61f4 data-v-86d1bed8><a class="title" href="./" data-v-86d1bed8><!--[--><!--]--><!--[--><img class="VPImage logo" src="./icon-radius.png" alt data-v-8426fc1a><!--]--><!--[-->落光的Pro博客<!--]--><!--[--><!--]--></a></div></div><div class="content" data-v-a0fd61f4><div class="curtain" data-v-a0fd61f4></div><div class="content-body" data-v-a0fd61f4><!--[--><!--]--><div class="VPNavBarSearch search" style="--vp-meta-key:&#39;Meta&#39;;" data-v-a0fd61f4><!--[--><!----><div id="local-search"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg class="DocSearch-Search-Icon" width="20" height="20" viewBox="0 0 20 20" aria-label="search icon"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-a0fd61f4 data-v-7f418b0f><span id="main-nav-aria-label" class="visually-hidden" data-v-7f418b0f>Main Navigation</span><!--[--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-9c007e85><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-9c007e85><span class="text" data-v-9c007e85><!----><span data-v-9c007e85>大前端</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-9c007e85><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-9c007e85><div class="VPMenu" data-v-9c007e85 data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuLink" data-v-e7ea1737 data-v-43f1e123><a class="VPLink link" href="./largeFrontEnd/webFrontEnd/md/01.html" data-v-43f1e123><!--[-->Web前端<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-e7ea1737 data-v-43f1e123><a class="VPLink link" href="./largeFrontEnd/uniapp/" data-v-43f1e123><!--[-->Uni-app<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-e7ea1737 data-v-43f1e123><a class="VPLink link" href="./largeFrontEnd/weChatMiniProgram/" data-v-43f1e123><!--[-->微信小程序<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-e7ea1737 data-v-43f1e123><a class="VPLink link" href="./largeFrontEnd/electron/" data-v-43f1e123><!--[-->Electron<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-e7ea1737 data-v-43f1e123><a class="VPLink link" href="./largeFrontEnd/flutter/" data-v-43f1e123><!--[-->Flutter<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-e7ea1737 data-v-43f1e123><a class="VPLink link" href="./largeFrontEnd/interview/01.html" data-v-43f1e123><!--[-->前端面试题<!--]--></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="./backEnd/" tabindex="0" data-v-7f418b0f data-v-42ef59de><!--[--><span data-v-42ef59de>后端</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="./linux/" tabindex="0" data-v-7f418b0f data-v-42ef59de><!--[--><span data-v-42ef59de>Linux</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="./myTeam/" tabindex="0" data-v-7f418b0f data-v-42ef59de><!--[--><span data-v-42ef59de>我的团队</span><!--]--></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-a0fd61f4 data-v-f6a63727><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title="toggle dark mode" aria-checked="false" data-v-f6a63727 data-v-ce54a7d1 data-v-b1685198><span class="check" data-v-b1685198><span class="icon" data-v-b1685198><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-ce54a7d1><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-ce54a7d1><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-a0fd61f4 data-v-0394ad82 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://gitee.com/luoguangguang" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink no-icon" href="..." aria-label="cool link" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Dribbble</title><path d="M12...6.38z"/></svg></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-a0fd61f4 data-v-40855f84 data-v-9c007e85><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-9c007e85><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-9c007e85><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-9c007e85><div class="VPMenu" data-v-9c007e85 data-v-e7ea1737><!----><!--[--><!--[--><!----><div class="group" data-v-40855f84><div class="item appearance" data-v-40855f84><p class="label" data-v-40855f84>Appearance</p><div class="appearance-action" data-v-40855f84><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title="toggle dark mode" aria-checked="false" data-v-40855f84 data-v-ce54a7d1 data-v-b1685198><span class="check" data-v-b1685198><span class="icon" data-v-b1685198><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-ce54a7d1><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-ce54a7d1><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div></div></div><div class="group" data-v-40855f84><div class="item social-links" data-v-40855f84><div class="VPSocialLinks social-links-list" data-v-40855f84 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://gitee.com/luoguangguang" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink no-icon" href="..." aria-label="cool link" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Dribbble</title><path d="M12...6.38z"/></svg></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-a0fd61f4 data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div></div><!----></header><div class="VPLocalNav reached-top" data-v-1919c326 data-v-79c8c1df><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-79c8c1df><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-79c8c1df><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-79c8c1df>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-79c8c1df data-v-1c15a60a><button data-v-1c15a60a>Return to top</button><!----></div></div><aside class="VPSidebar" data-v-1919c326 data-v-b00e2fdd><div class="curtain" data-v-b00e2fdd></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-b00e2fdd><span class="visually-hidden" id="sidebar-aria-label" data-v-b00e2fdd> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="group" data-v-b00e2fdd><section class="VPSidebarItem level-0 collapsible" data-v-b00e2fdd data-v-e31bd47b><div class="item" role="button" tabindex="0" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><h2 class="text" data-v-e31bd47b>Flutter入门到实战</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-e31bd47b><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-e31bd47b><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-e31bd47b><!--[--><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter1/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第一章 初识Flutter</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter2/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第二章 简介</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter3/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第三章 基础组件</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter4/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第四章 布局类组件</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter5/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第五章 容器类Widget</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter6/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第六章 可滚动组件</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter7/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第七章 功能型Widget简介</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter8/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第八章 事件处理与通知</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter9/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第九章 动画</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter10/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第十章 自定义组件</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter11/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第十一章 文件操作</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter12/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第十二章 Flutter 扩展</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter13/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第十三章 多语言</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-e31bd47b data-v-e31bd47b><div class="item" data-v-e31bd47b><div class="indicator" data-v-e31bd47b></div><a class="VPLink link link" href="./largeFrontEnd/flutter/chapter14/index.html" data-v-e31bd47b><!--[--><p class="text" data-v-e31bd47b>第十四章 高级进阶</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-1919c326 data-v-669faec9><div class="VPDoc has-sidebar has-aside" data-v-669faec9 data-v-6b87e69f><!--[--><!--]--><div class="container" data-v-6b87e69f><div class="aside" data-v-6b87e69f><div class="aside-curtain" data-v-6b87e69f></div><div class="aside-container" data-v-6b87e69f><div class="aside-content" data-v-6b87e69f><div class="VPDocAside" data-v-6b87e69f data-v-3f215769><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" role="navigation" data-v-3f215769 data-v-6ae8e080><div class="content" data-v-6ae8e080><div class="outline-marker" data-v-6ae8e080></div><div class="outline-title" role="heading" data-v-6ae8e080>On this page</div><nav aria-labelledby="doc-outline-aria-label" data-v-6ae8e080><span class="visually-hidden" id="doc-outline-aria-label" data-v-6ae8e080> Table of Contents for current page </span><ul class="root" data-v-6ae8e080 data-v-d0ee3533><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-3f215769></div><!--[--><!--]--><div class="VPDocAsideCarbonAds" data-v-3f215769><div class="VPCarbonAds" data-v-2e1efd59></div></div><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-6b87e69f><div class="content-container" data-v-6b87e69f><!--[--><!--]--><!----><main class="main" data-v-6b87e69f><div style="position:relative;" class="vp-doc _largeFrontEnd_flutter_chapter7_dailog" data-v-6b87e69f><div><h1 id="_7-7-对话框详解" tabindex="-1">7.7 对话框详解 <a class="header-anchor" href="#_7-7-对话框详解" aria-label="Permalink to &quot;7.7 对话框详解&quot;">​</a></h1><p>本节将详细介绍一下Flutter中对话框的使用方式、实现原理、样式定制及状态管理。</p><h2 id="_7-7-1-使用对话框" tabindex="-1">7.7.1 使用对话框 <a class="header-anchor" href="#_7-7-1-使用对话框" aria-label="Permalink to &quot;7.7.1 使用对话框&quot;">​</a></h2><p>对话框本质上也是UI布局，通常一个对话框会包含标题、内容，以及一些操作按钮，为此，Material库中提供了一些现成的对话框组件来用于快速的构建出一个完整的对话框。</p><h3 id="_1-alertdialog" tabindex="-1">1. AlertDialog <a class="header-anchor" href="#_1-alertdialog" aria-label="Permalink to &quot;1. AlertDialog&quot;">​</a></h3><p>下面我们主要介绍一下Material库中的<code>AlertDialog</code>组件，它的构造函数定义如下：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">({</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Key</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> key,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.title, </span><span style="color:#6A737D;">//对话框标题组件</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.titlePadding, </span><span style="color:#6A737D;">// 标题填充</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.titleTextStyle, </span><span style="color:#6A737D;">//标题文本样式</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.content, </span><span style="color:#6A737D;">// 对话框内容组件</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.contentPadding </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">EdgeInsets</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">fromLTRB</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">24.0</span><span style="color:#E1E4E8;">, </span><span style="color:#79B8FF;">20.0</span><span style="color:#E1E4E8;">, </span><span style="color:#79B8FF;">24.0</span><span style="color:#E1E4E8;">, </span><span style="color:#79B8FF;">24.0</span><span style="color:#E1E4E8;">), </span><span style="color:#6A737D;">//内容的填充</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.contentTextStyle,</span><span style="color:#6A737D;">// 内容文本样式</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.actions, </span><span style="color:#6A737D;">// 对话框操作按钮组</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.backgroundColor, </span><span style="color:#6A737D;">// 对话框背景色</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.elevation,</span><span style="color:#6A737D;">// 对话框的阴影</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.semanticLabel, </span><span style="color:#6A737D;">//对话框语义化标签(用于读屏软件)</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.shape, </span><span style="color:#6A737D;">// 对话框外形</span></span>
<span class="line"><span style="color:#E1E4E8;">})</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">({</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Key</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> key,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.title, </span><span style="color:#6A737D;">//对话框标题组件</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.titlePadding, </span><span style="color:#6A737D;">// 标题填充</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.titleTextStyle, </span><span style="color:#6A737D;">//标题文本样式</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.content, </span><span style="color:#6A737D;">// 对话框内容组件</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.contentPadding </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">EdgeInsets</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">fromLTRB</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">24.0</span><span style="color:#24292E;">, </span><span style="color:#005CC5;">20.0</span><span style="color:#24292E;">, </span><span style="color:#005CC5;">24.0</span><span style="color:#24292E;">, </span><span style="color:#005CC5;">24.0</span><span style="color:#24292E;">), </span><span style="color:#6A737D;">//内容的填充</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.contentTextStyle,</span><span style="color:#6A737D;">// 内容文本样式</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.actions, </span><span style="color:#6A737D;">// 对话框操作按钮组</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.backgroundColor, </span><span style="color:#6A737D;">// 对话框背景色</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.elevation,</span><span style="color:#6A737D;">// 对话框的阴影</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.semanticLabel, </span><span style="color:#6A737D;">//对话框语义化标签(用于读屏软件)</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.shape, </span><span style="color:#6A737D;">// 对话框外形</span></span>
<span class="line"><span style="color:#24292E;">})</span></span></code></pre></div><p>参数都比较简单，不在赘述。下面我们看一个例子，假如我们要在删除文件时弹出一个确认对话框，该对话框如图7-11所示：</p><p><img src="/assets/7-11.a5c62ffb.png" alt="图7-11"></p><p>该对话框样式代码如下：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;提示&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">  content</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">  actions</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;取消&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">      onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(), </span><span style="color:#6A737D;">//关闭对话框</span></span>
<span class="line"><span style="color:#E1E4E8;">    ),</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;删除&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">      onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () {</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#6A737D;">// ... 执行删除操作</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">true</span><span style="color:#E1E4E8;">); </span><span style="color:#6A737D;">//关闭对话框</span></span>
<span class="line"><span style="color:#E1E4E8;">      },</span></span>
<span class="line"><span style="color:#E1E4E8;">    ),</span></span>
<span class="line"><span style="color:#E1E4E8;">  ],</span></span>
<span class="line"><span style="color:#E1E4E8;">);</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;提示&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">  content</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">  actions</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;取消&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">      onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(), </span><span style="color:#6A737D;">//关闭对话框</span></span>
<span class="line"><span style="color:#24292E;">    ),</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;删除&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">      onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () {</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#6A737D;">// ... 执行删除操作</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">true</span><span style="color:#24292E;">); </span><span style="color:#6A737D;">//关闭对话框</span></span>
<span class="line"><span style="color:#24292E;">      },</span></span>
<span class="line"><span style="color:#24292E;">    ),</span></span>
<span class="line"><span style="color:#24292E;">  ],</span></span>
<span class="line"><span style="color:#24292E;">);</span></span></code></pre></div><p>实现代码很简单，不在赘述。唯一需要注意的是我们是通过<code>Navigator.of(context).pop(…)</code>方法来关闭对话框的，这和路由返回的方式是一致的，并且都可以返回一个结果数据。现在，对话框我们已经构建好了，那么如何将它弹出来呢？还有对话框返回的数据应如何被接收呢？这些问题的答案都在<code>showDialog()</code>方法中。</p><p><code>showDialog()</code>是Material组件库提供的一个用于弹出Material风格对话框的方法，签名如下：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">showDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;">&gt;({</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">WidgetBuilder</span><span style="color:#E1E4E8;"> builder, </span><span style="color:#6A737D;">// 对话框UI的builder</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> barrierDismissible </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">true</span><span style="color:#E1E4E8;">, </span><span style="color:#6A737D;">//点击对话框barrier(遮罩)时是否关闭它</span></span>
<span class="line"><span style="color:#E1E4E8;">})</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">showDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;">&gt;({</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">WidgetBuilder</span><span style="color:#24292E;"> builder, </span><span style="color:#6A737D;">// 对话框UI的builder</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> barrierDismissible </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">true</span><span style="color:#24292E;">, </span><span style="color:#6A737D;">//点击对话框barrier(遮罩)时是否关闭它</span></span>
<span class="line"><span style="color:#24292E;">})</span></span></code></pre></div><p>该方法只有两个参数，含义见注释。该方法返回一个<code>Future</code>，它正是用于接收对话框的返回值：如果我们是通过点击对话框遮罩关闭的，则<code>Future</code>的值为<code>null</code>，否则为我们通过<code>Navigator.of(context).pop(result)</code>返回的result值，下面我们看一下整个示例：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#6A737D;">//点击该按钮后弹出对话框</span></span>
<span class="line"><span style="color:#79B8FF;">ElevatedButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;对话框1&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">  onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">async</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#6A737D;">//弹出对话框并等待其关闭</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">bool</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> delete </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">await</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDeleteConfirmDialog1</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#F97583;">if</span><span style="color:#E1E4E8;"> (delete </span><span style="color:#F97583;">==</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">null</span><span style="color:#E1E4E8;">) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;取消删除&quot;</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">    } </span><span style="color:#F97583;">else</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;已确认删除&quot;</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#6A737D;">//... 删除文件</span></span>
<span class="line"><span style="color:#E1E4E8;">    }</span></span>
<span class="line"><span style="color:#E1E4E8;">  },</span></span>
<span class="line"><span style="color:#E1E4E8;">),</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D;">// 弹出对话框</span></span>
<span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">showDeleteConfirmDialog1</span><span style="color:#E1E4E8;">() {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">&gt;(</span></span>
<span class="line"><span style="color:#E1E4E8;">    context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">        title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;提示&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">        content</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">        actions</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;取消&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(), </span><span style="color:#6A737D;">// 关闭对话框</span></span>
<span class="line"><span style="color:#E1E4E8;">          ),</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;删除&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () {</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#6A737D;">//关闭对话框并返回true</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">true</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">            },</span></span>
<span class="line"><span style="color:#E1E4E8;">          ),</span></span>
<span class="line"><span style="color:#E1E4E8;">        ],</span></span>
<span class="line"><span style="color:#E1E4E8;">      );</span></span>
<span class="line"><span style="color:#E1E4E8;">    },</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#6A737D;">//点击该按钮后弹出对话框</span></span>
<span class="line"><span style="color:#005CC5;">ElevatedButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;对话框1&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">  onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">async</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#6A737D;">//弹出对话框并等待其关闭</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">bool</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> delete </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">await</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDeleteConfirmDialog1</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#D73A49;">if</span><span style="color:#24292E;"> (delete </span><span style="color:#D73A49;">==</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">null</span><span style="color:#24292E;">) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;取消删除&quot;</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">    } </span><span style="color:#D73A49;">else</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;已确认删除&quot;</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#6A737D;">//... 删除文件</span></span>
<span class="line"><span style="color:#24292E;">    }</span></span>
<span class="line"><span style="color:#24292E;">  },</span></span>
<span class="line"><span style="color:#24292E;">),</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D;">// 弹出对话框</span></span>
<span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">showDeleteConfirmDialog1</span><span style="color:#24292E;">() {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">&gt;(</span></span>
<span class="line"><span style="color:#24292E;">    context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (context) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">        title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;提示&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">        content</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">        actions</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;取消&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(), </span><span style="color:#6A737D;">// 关闭对话框</span></span>
<span class="line"><span style="color:#24292E;">          ),</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;删除&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () {</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#6A737D;">//关闭对话框并返回true</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">true</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">            },</span></span>
<span class="line"><span style="color:#24292E;">          ),</span></span>
<span class="line"><span style="color:#24292E;">        ],</span></span>
<span class="line"><span style="color:#24292E;">      );</span></span>
<span class="line"><span style="color:#24292E;">    },</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>示例运行后，我们点击对话框“取消”按钮或遮罩，控制台就会输出&quot;取消删除&quot;，如果点击“删除”按钮，控制台就会输出&quot;已确认删除&quot;。</p><blockquote><p>注意：如果<code>AlertDialog</code>的内容过长，内容将会溢出，这在很多时候可能不是我们期望的，所以如果对话框内容过长时，可以用<code>SingleChildScrollView</code>将内容包裹起来。</p></blockquote><h3 id="_2-simpledialog" tabindex="-1">2. SimpleDialog <a class="header-anchor" href="#_2-simpledialog" aria-label="Permalink to &quot;2. SimpleDialog&quot;">​</a></h3><p><code>SimpleDialog</code>也是Material组件库提供的对话框，它会展示一个列表，用于列表选择的场景。下面是一个选择APP语言的示例，运行结果如图7-12。</p><p><img src="/assets/7-12.7b90716f.png" alt="图7-12"></p><p>实现代码如下：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#F97583;">void</span><span style="color:#E1E4E8;">&gt; </span><span style="color:#B392F0;">changeLanguage</span><span style="color:#E1E4E8;">() </span><span style="color:#F97583;">async</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">int</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> i </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">await</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">int</span><span style="color:#E1E4E8;">&gt;(</span></span>
<span class="line"><span style="color:#E1E4E8;">      context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">      builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">SimpleDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&#39;请选择语言&#39;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">          children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">SimpleDialogOption</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">              onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () {</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#6A737D;">// 返回1</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(context, </span><span style="color:#79B8FF;">1</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">              },</span></span>
<span class="line"><span style="color:#E1E4E8;">              child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Padding</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">                padding</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">EdgeInsets</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">symmetric</span><span style="color:#E1E4E8;">(vertical</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">6</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">                child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&#39;中文简体&#39;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">              ),</span></span>
<span class="line"><span style="color:#E1E4E8;">            ),</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">SimpleDialogOption</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">              onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () {</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#6A737D;">// 返回2</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(context, </span><span style="color:#79B8FF;">2</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">              },</span></span>
<span class="line"><span style="color:#E1E4E8;">              child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Padding</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">                padding</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">EdgeInsets</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">symmetric</span><span style="color:#E1E4E8;">(vertical</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">6</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">                child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&#39;美国英语&#39;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">              ),</span></span>
<span class="line"><span style="color:#E1E4E8;">            ),</span></span>
<span class="line"><span style="color:#E1E4E8;">          ],</span></span>
<span class="line"><span style="color:#E1E4E8;">        );</span></span>
<span class="line"><span style="color:#E1E4E8;">      });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">if</span><span style="color:#E1E4E8;"> (i </span><span style="color:#F97583;">!=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">null</span><span style="color:#E1E4E8;">) {</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;选择了：${</span><span style="color:#79B8FF;">i</span><span style="color:#9ECBFF;"> == </span><span style="color:#79B8FF;">1</span><span style="color:#9ECBFF;"> ? &quot;中文简体&quot; : &quot;美国英语&quot;}&quot;</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">  }</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#D73A49;">void</span><span style="color:#24292E;">&gt; </span><span style="color:#6F42C1;">changeLanguage</span><span style="color:#24292E;">() </span><span style="color:#D73A49;">async</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">int</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> i </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">await</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">int</span><span style="color:#24292E;">&gt;(</span></span>
<span class="line"><span style="color:#24292E;">      context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">      builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context) {</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">SimpleDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&#39;请选择语言&#39;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">          children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">SimpleDialogOption</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">              onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () {</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#6A737D;">// 返回1</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(context, </span><span style="color:#005CC5;">1</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">              },</span></span>
<span class="line"><span style="color:#24292E;">              child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Padding</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">                padding</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">EdgeInsets</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">symmetric</span><span style="color:#24292E;">(vertical</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">6</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">                child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&#39;中文简体&#39;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">              ),</span></span>
<span class="line"><span style="color:#24292E;">            ),</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">SimpleDialogOption</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">              onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () {</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#6A737D;">// 返回2</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(context, </span><span style="color:#005CC5;">2</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">              },</span></span>
<span class="line"><span style="color:#24292E;">              child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Padding</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">                padding</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">EdgeInsets</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">symmetric</span><span style="color:#24292E;">(vertical</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">6</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">                child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&#39;美国英语&#39;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">              ),</span></span>
<span class="line"><span style="color:#24292E;">            ),</span></span>
<span class="line"><span style="color:#24292E;">          ],</span></span>
<span class="line"><span style="color:#24292E;">        );</span></span>
<span class="line"><span style="color:#24292E;">      });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">if</span><span style="color:#24292E;"> (i </span><span style="color:#D73A49;">!=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">null</span><span style="color:#24292E;">) {</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;选择了：${</span><span style="color:#005CC5;">i</span><span style="color:#032F62;"> == </span><span style="color:#005CC5;">1</span><span style="color:#032F62;"> ? &quot;中文简体&quot; : &quot;美国英语&quot;}&quot;</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">  }</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>列表项组件我们使用了<code>SimpleDialogOption</code>组件来包装了一下，它相当于一个TextButton，只不过按钮文案是左对齐的，并且padding较小。上面示例运行后，用户选择一种语言后，控制台就会打印出它。</p><h3 id="_3-dialog" tabindex="-1">3. Dialog <a class="header-anchor" href="#_3-dialog" aria-label="Permalink to &quot;3. Dialog&quot;">​</a></h3><p>实际上<code>AlertDialog</code>和<code>SimpleDialog</code>都使用了<code>Dialog</code>类。由于<code>AlertDialog</code>和<code>SimpleDialog</code>中使用了<code>IntrinsicWidth</code>来尝试通过子组件的实际尺寸来调整自身尺寸，这就导致他们的子组件不能是延迟加载模型的组件（如<code>ListView</code>、<code>GridView</code> 、 <code>CustomScrollView</code>等），如下面的代码运行后会报错。</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  content</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ListView</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> ...</span><span style="color:#6A737D;">//省略</span></span>
<span class="line"><span style="color:#E1E4E8;">  ),</span></span>
<span class="line"><span style="color:#E1E4E8;">);</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  content</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ListView</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> ...</span><span style="color:#6A737D;">//省略</span></span>
<span class="line"><span style="color:#24292E;">  ),</span></span>
<span class="line"><span style="color:#24292E;">);</span></span></code></pre></div><p>如果我们就是需要嵌套一个<code>ListView</code>应该怎么做？这时，我们可以直接使用<code>Dialog</code>类，如：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Dialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ListView</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> ...</span><span style="color:#6A737D;">//省略</span></span>
<span class="line"><span style="color:#E1E4E8;">  ),</span></span>
<span class="line"><span style="color:#E1E4E8;">);</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Dialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ListView</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> ...</span><span style="color:#6A737D;">//省略</span></span>
<span class="line"><span style="color:#24292E;">  ),</span></span>
<span class="line"><span style="color:#24292E;">);</span></span></code></pre></div><p>下面我们看一个弹出一个有30个列表项的对话框示例，运行效果如图7-12所示：</p><p><img src="/assets/7-13.32816d35.png" alt="图7-13"></p><p>实现代码如下：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#F97583;">void</span><span style="color:#E1E4E8;">&gt; </span><span style="color:#B392F0;">showListDialog</span><span style="color:#E1E4E8;">() </span><span style="color:#F97583;">async</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">int</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> index </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">await</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">int</span><span style="color:#E1E4E8;">&gt;(</span></span>
<span class="line"><span style="color:#E1E4E8;">    context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">var</span><span style="color:#E1E4E8;"> child </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Column</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">        children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">ListTile</span><span style="color:#E1E4E8;">(title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;请选择&quot;</span><span style="color:#E1E4E8;">)),</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">Expanded</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">              child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ListView</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">builder</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            itemCount</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">30</span><span style="color:#E1E4E8;">,</span></span>
<span class="line"><span style="color:#E1E4E8;">            itemBuilder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context, </span><span style="color:#79B8FF;">int</span><span style="color:#E1E4E8;"> index) {</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ListTile</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">                title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;$</span><span style="color:#79B8FF;">index</span><span style="color:#9ECBFF;">&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">                onTap</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(index),</span></span>
<span class="line"><span style="color:#E1E4E8;">              );</span></span>
<span class="line"><span style="color:#E1E4E8;">            },</span></span>
<span class="line"><span style="color:#E1E4E8;">          )),</span></span>
<span class="line"><span style="color:#E1E4E8;">        ],</span></span>
<span class="line"><span style="color:#E1E4E8;">      );</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#6A737D;">//使用AlertDialog会报错</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#6A737D;">//return AlertDialog(content: child);</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Dialog</span><span style="color:#E1E4E8;">(child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> child);</span></span>
<span class="line"><span style="color:#E1E4E8;">    },</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">if</span><span style="color:#E1E4E8;"> (index </span><span style="color:#F97583;">!=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">null</span><span style="color:#E1E4E8;">) {</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;点击了：$</span><span style="color:#79B8FF;">index</span><span style="color:#9ECBFF;">&quot;</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">  }</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#D73A49;">void</span><span style="color:#24292E;">&gt; </span><span style="color:#6F42C1;">showListDialog</span><span style="color:#24292E;">() </span><span style="color:#D73A49;">async</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">int</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> index </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">await</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">int</span><span style="color:#24292E;">&gt;(</span></span>
<span class="line"><span style="color:#24292E;">    context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">var</span><span style="color:#24292E;"> child </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Column</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">        children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">ListTile</span><span style="color:#24292E;">(title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;请选择&quot;</span><span style="color:#24292E;">)),</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">Expanded</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">              child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ListView</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">builder</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            itemCount</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">30</span><span style="color:#24292E;">,</span></span>
<span class="line"><span style="color:#24292E;">            itemBuilder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context, </span><span style="color:#005CC5;">int</span><span style="color:#24292E;"> index) {</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ListTile</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">                title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;$</span><span style="color:#005CC5;">index</span><span style="color:#032F62;">&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">                onTap</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(index),</span></span>
<span class="line"><span style="color:#24292E;">              );</span></span>
<span class="line"><span style="color:#24292E;">            },</span></span>
<span class="line"><span style="color:#24292E;">          )),</span></span>
<span class="line"><span style="color:#24292E;">        ],</span></span>
<span class="line"><span style="color:#24292E;">      );</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#6A737D;">//使用AlertDialog会报错</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#6A737D;">//return AlertDialog(content: child);</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Dialog</span><span style="color:#24292E;">(child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> child);</span></span>
<span class="line"><span style="color:#24292E;">    },</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">if</span><span style="color:#24292E;"> (index </span><span style="color:#D73A49;">!=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">null</span><span style="color:#24292E;">) {</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;点击了：$</span><span style="color:#005CC5;">index</span><span style="color:#032F62;">&quot;</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">  }</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>现在，我们己经介绍完了<code>AlertDialog</code>、<code>SimpleDialog</code>以及<code>Dialog</code>。上面的示例中，我们在调用<code>showDialog</code>时，在<code>builder</code>中都是构建了这三个对话框组件的一种，可能有些读者会惯性的以为在<code>builder</code>中只能返回这三者之一，其实这不是必须的！就拿<code>Dialog</code>的示例来举例，我们完全可以用下面的代码来替代<code>Dialog</code>：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#6A737D;">// return Dialog(child: child) </span></span>
<span class="line"><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">UnconstrainedBox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  constrainedAxis</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Axis</span><span style="color:#E1E4E8;">.vertical,</span></span>
<span class="line"><span style="color:#E1E4E8;">  child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ConstrainedBox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    constraints</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">BoxConstraints</span><span style="color:#E1E4E8;">(maxWidth</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">280</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">    child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Material</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> child,</span></span>
<span class="line"><span style="color:#E1E4E8;">      type</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">MaterialType</span><span style="color:#E1E4E8;">.card,</span></span>
<span class="line"><span style="color:#E1E4E8;">    ),</span></span>
<span class="line"><span style="color:#E1E4E8;">  ),</span></span>
<span class="line"><span style="color:#E1E4E8;">);</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#6A737D;">// return Dialog(child: child) </span></span>
<span class="line"><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">UnconstrainedBox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  constrainedAxis</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Axis</span><span style="color:#24292E;">.vertical,</span></span>
<span class="line"><span style="color:#24292E;">  child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ConstrainedBox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    constraints</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">BoxConstraints</span><span style="color:#24292E;">(maxWidth</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">280</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">    child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Material</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> child,</span></span>
<span class="line"><span style="color:#24292E;">      type</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">MaterialType</span><span style="color:#24292E;">.card,</span></span>
<span class="line"><span style="color:#24292E;">    ),</span></span>
<span class="line"><span style="color:#24292E;">  ),</span></span>
<span class="line"><span style="color:#24292E;">);</span></span></code></pre></div><p>上面代码运行后可以实现一样的效果。现在我们总结一下：<code>AlertDialog</code>、<code>SimpleDialog</code>以及<code>Dialog</code>是Material组件库提供的三种对话框，旨在帮助开发者快速构建出符合Material设计规范的对话框，但读者完全可以自定义对话框样式，因此，我们仍然可以实现各种样式的对话框，这样即带来了易用性，又有很强的扩展性。</p><h2 id="_7-7-2-对话框打开动画及遮罩" tabindex="-1">7.7.2 对话框打开动画及遮罩 <a class="header-anchor" href="#_7-7-2-对话框打开动画及遮罩" aria-label="Permalink to &quot;7.7.2 对话框打开动画及遮罩&quot;">​</a></h2><p>我们可以把对话框分为内部样式和外部样式两部分。内部样式指对话框中显示的具体内容，这部分内容我们已经在上面介绍过了；外部样式包含对话框遮罩样式、打开动画等，本节主要介绍如何自定义这些外部样式。</p><blockquote><p>关于动画相关内容我们将在本书第九章中详细介绍，下面内容读者可以先了解一下（不必深究），读者可以在学习完动画相关内容后再回头来看。</p></blockquote><p>我们已经介绍过了<code>showDialog</code>方法，它是Material组件库中提供的一个打开Material风格对话框的方法。那如何打开一个普通风格的对话框呢（非Material风格）？ Flutter 提供了一个<code>showGeneralDialog</code>方法，签名如下：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">showGeneralDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;">&gt;({</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">RoutePageBuilder</span><span style="color:#E1E4E8;"> pageBuilder, </span><span style="color:#6A737D;">//构建对话框内部UI</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> barrierDismissible </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">false</span><span style="color:#E1E4E8;">, </span><span style="color:#6A737D;">//点击遮罩是否关闭对话框</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">String</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> barrierLabel, </span><span style="color:#6A737D;">// 语义化标签(用于读屏软件)</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Color</span><span style="color:#E1E4E8;"> barrierColor </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Color</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">0x80000000</span><span style="color:#E1E4E8;">), </span><span style="color:#6A737D;">// 遮罩颜色</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Duration</span><span style="color:#E1E4E8;"> transitionDuration </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Duration</span><span style="color:#E1E4E8;">(milliseconds</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">200</span><span style="color:#E1E4E8;">), </span><span style="color:#6A737D;">// 对话框打开/关闭的动画时长</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">RouteTransitionsBuilder</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> transitionBuilder, </span><span style="color:#6A737D;">// 对话框打开/关闭的动画</span></span>
<span class="line"><span style="color:#E1E4E8;">  ...</span></span>
<span class="line"><span style="color:#E1E4E8;">})</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">showGeneralDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;">&gt;({</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">RoutePageBuilder</span><span style="color:#24292E;"> pageBuilder, </span><span style="color:#6A737D;">//构建对话框内部UI</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> barrierDismissible </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">false</span><span style="color:#24292E;">, </span><span style="color:#6A737D;">//点击遮罩是否关闭对话框</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">String</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> barrierLabel, </span><span style="color:#6A737D;">// 语义化标签(用于读屏软件)</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Color</span><span style="color:#24292E;"> barrierColor </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Color</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">0x80000000</span><span style="color:#24292E;">), </span><span style="color:#6A737D;">// 遮罩颜色</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Duration</span><span style="color:#24292E;"> transitionDuration </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Duration</span><span style="color:#24292E;">(milliseconds</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">200</span><span style="color:#24292E;">), </span><span style="color:#6A737D;">// 对话框打开/关闭的动画时长</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">RouteTransitionsBuilder</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> transitionBuilder, </span><span style="color:#6A737D;">// 对话框打开/关闭的动画</span></span>
<span class="line"><span style="color:#24292E;">  ...</span></span>
<span class="line"><span style="color:#24292E;">})</span></span></code></pre></div><p>实际上，<code>showDialog</code>方法正是<code>showGeneralDialog</code>的一个封装，定制了Material风格对话框的遮罩颜色和动画。Material风格对话框打开/关闭动画是一个Fade（渐隐渐显）动画，如果我们想使用一个缩放动画就可以通过<code>transitionBuilder</code>来自定义。下面我们自己封装一个<code>showCustomDialog</code>方法，它定制的对话框动画为缩放动画，并同时制定遮罩颜色为<code>Colors.black87</code>：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">showCustomDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;">&gt;({</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> barrierDismissible </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">true</span><span style="color:#E1E4E8;">,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">WidgetBuilder</span><span style="color:#E1E4E8;"> builder,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">ThemeData</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> theme,</span></span>
<span class="line"><span style="color:#E1E4E8;">}) {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">final</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ThemeData</span><span style="color:#E1E4E8;"> theme </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Theme</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context, shadowThemeOnly</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">true</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showGeneralDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    pageBuilder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> buildContext, </span><span style="color:#79B8FF;">Animation</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">double</span><span style="color:#E1E4E8;">&gt; animation,</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#79B8FF;">Animation</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">double</span><span style="color:#E1E4E8;">&gt; secondaryAnimation) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">final</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Widget</span><span style="color:#E1E4E8;"> pageChild </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Builder</span><span style="color:#E1E4E8;">(builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> builder);</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">SafeArea</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">        child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Builder</span><span style="color:#E1E4E8;">(builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> theme </span><span style="color:#F97583;">!=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">null</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Theme</span><span style="color:#E1E4E8;">(data</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> theme, child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> pageChild)</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> pageChild;</span></span>
<span class="line"><span style="color:#E1E4E8;">        }),</span></span>
<span class="line"><span style="color:#E1E4E8;">      );</span></span>
<span class="line"><span style="color:#E1E4E8;">    },</span></span>
<span class="line"><span style="color:#E1E4E8;">    barrierDismissible</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> barrierDismissible,</span></span>
<span class="line"><span style="color:#E1E4E8;">    barrierLabel</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">MaterialLocalizations</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).modalBarrierDismissLabel,</span></span>
<span class="line"><span style="color:#E1E4E8;">    barrierColor</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Colors</span><span style="color:#E1E4E8;">.black87, </span><span style="color:#6A737D;">// 自定义遮罩颜色</span></span>
<span class="line"><span style="color:#E1E4E8;">    transitionDuration</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Duration</span><span style="color:#E1E4E8;">(milliseconds</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">150</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">    transitionBuilder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> _buildMaterialDialogTransitions,</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF;">Widget</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">_buildMaterialDialogTransitions</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">Animation</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">double</span><span style="color:#E1E4E8;">&gt; animation,</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">Animation</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">double</span><span style="color:#E1E4E8;">&gt; secondaryAnimation,</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">Widget</span><span style="color:#E1E4E8;"> child) {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#6A737D;">// 使用缩放动画</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ScaleTransition</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    scale</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">CurvedAnimation</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      parent</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> animation,</span></span>
<span class="line"><span style="color:#E1E4E8;">      curve</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Curves</span><span style="color:#E1E4E8;">.easeOut,</span></span>
<span class="line"><span style="color:#E1E4E8;">    ),</span></span>
<span class="line"><span style="color:#E1E4E8;">    child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> child,</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">showCustomDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;">&gt;({</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> barrierDismissible </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">true</span><span style="color:#24292E;">,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">WidgetBuilder</span><span style="color:#24292E;"> builder,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">ThemeData</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> theme,</span></span>
<span class="line"><span style="color:#24292E;">}) {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">final</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ThemeData</span><span style="color:#24292E;"> theme </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Theme</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context, shadowThemeOnly</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">true</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showGeneralDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    pageBuilder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> buildContext, </span><span style="color:#005CC5;">Animation</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">double</span><span style="color:#24292E;">&gt; animation,</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#005CC5;">Animation</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">double</span><span style="color:#24292E;">&gt; secondaryAnimation) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">final</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Widget</span><span style="color:#24292E;"> pageChild </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Builder</span><span style="color:#24292E;">(builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> builder);</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">SafeArea</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">        child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Builder</span><span style="color:#24292E;">(builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context) {</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> theme </span><span style="color:#D73A49;">!=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">null</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Theme</span><span style="color:#24292E;">(data</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> theme, child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> pageChild)</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> pageChild;</span></span>
<span class="line"><span style="color:#24292E;">        }),</span></span>
<span class="line"><span style="color:#24292E;">      );</span></span>
<span class="line"><span style="color:#24292E;">    },</span></span>
<span class="line"><span style="color:#24292E;">    barrierDismissible</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> barrierDismissible,</span></span>
<span class="line"><span style="color:#24292E;">    barrierLabel</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">MaterialLocalizations</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).modalBarrierDismissLabel,</span></span>
<span class="line"><span style="color:#24292E;">    barrierColor</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Colors</span><span style="color:#24292E;">.black87, </span><span style="color:#6A737D;">// 自定义遮罩颜色</span></span>
<span class="line"><span style="color:#24292E;">    transitionDuration</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Duration</span><span style="color:#24292E;">(milliseconds</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">150</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">    transitionBuilder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> _buildMaterialDialogTransitions,</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#005CC5;">Widget</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">_buildMaterialDialogTransitions</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">Animation</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">double</span><span style="color:#24292E;">&gt; animation,</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">Animation</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">double</span><span style="color:#24292E;">&gt; secondaryAnimation,</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">Widget</span><span style="color:#24292E;"> child) {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#6A737D;">// 使用缩放动画</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ScaleTransition</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    scale</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">CurvedAnimation</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      parent</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> animation,</span></span>
<span class="line"><span style="color:#24292E;">      curve</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Curves</span><span style="color:#24292E;">.easeOut,</span></span>
<span class="line"><span style="color:#24292E;">    ),</span></span>
<span class="line"><span style="color:#24292E;">    child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> child,</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>现在，我们使用<code>showCustomDialog</code>打开文件删除确认对话框，代码如下：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#E1E4E8;">... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#B392F0;">showCustomDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">&gt;(</span></span>
<span class="line"><span style="color:#E1E4E8;">  context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">  builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;提示&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">      content</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">      actions</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;取消&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">          onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(),</span></span>
<span class="line"><span style="color:#E1E4E8;">        ),</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;删除&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">          onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () {</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#6A737D;">// 执行删除操作</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">true</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">          },</span></span>
<span class="line"><span style="color:#E1E4E8;">        ),</span></span>
<span class="line"><span style="color:#E1E4E8;">      ],</span></span>
<span class="line"><span style="color:#E1E4E8;">    );</span></span>
<span class="line"><span style="color:#E1E4E8;">  },</span></span>
<span class="line"><span style="color:#E1E4E8;">);</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#24292E;">... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#6F42C1;">showCustomDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">&gt;(</span></span>
<span class="line"><span style="color:#24292E;">  context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">  builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (context) {</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;提示&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">      content</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">      actions</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;取消&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">          onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(),</span></span>
<span class="line"><span style="color:#24292E;">        ),</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;删除&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">          onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () {</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#6A737D;">// 执行删除操作</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">true</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">          },</span></span>
<span class="line"><span style="color:#24292E;">        ),</span></span>
<span class="line"><span style="color:#24292E;">      ],</span></span>
<span class="line"><span style="color:#24292E;">    );</span></span>
<span class="line"><span style="color:#24292E;">  },</span></span>
<span class="line"><span style="color:#24292E;">);</span></span></code></pre></div><p>运行效果如图7-14所示：</p><p><img src="/assets/7-14.5d634ab0.png" alt="图7-14"></p><p>可以发现，遮罩颜色比通过<code>showDialog</code>方法打开的对话框更深。另外对话框打开/关闭的动画已变为缩放动画了，读者可以亲自运行示例查看效果。</p><h2 id="_7-7-3-对话框实现原理" tabindex="-1">7.7.3 对话框实现原理 <a class="header-anchor" href="#_7-7-3-对话框实现原理" aria-label="Permalink to &quot;7.7.3 对话框实现原理&quot;">​</a></h2><p>我们以<code>showGeneralDialog</code>方法为例来看看它的具体实现：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">showGeneralDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">extends</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Object</span><span style="color:#E1E4E8;">?&gt;({</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">RoutePageBuilder</span><span style="color:#E1E4E8;"> pageBuilder,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> barrierDismissible </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">false</span><span style="color:#E1E4E8;">,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">String</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> barrierLabel,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Color</span><span style="color:#E1E4E8;"> barrierColor </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Color</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">0x80000000</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Duration</span><span style="color:#E1E4E8;"> transitionDuration </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Duration</span><span style="color:#E1E4E8;">(milliseconds</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">200</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">RouteTransitionsBuilder</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> transitionBuilder,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> useRootNavigator </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">true</span><span style="color:#E1E4E8;">,</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">RouteSettings</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> routeSettings,</span></span>
<span class="line"><span style="color:#E1E4E8;">}) {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context, rootNavigator</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> useRootNavigator).</span><span style="color:#B392F0;">push</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;">&gt;(</span><span style="color:#79B8FF;">RawDialogRoute</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">T</span><span style="color:#E1E4E8;">&gt;(</span></span>
<span class="line"><span style="color:#E1E4E8;">    pageBuilder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> pageBuilder,</span></span>
<span class="line"><span style="color:#E1E4E8;">    barrierDismissible</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> barrierDismissible,</span></span>
<span class="line"><span style="color:#E1E4E8;">    barrierLabel</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> barrierLabel,</span></span>
<span class="line"><span style="color:#E1E4E8;">    barrierColor</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> barrierColor,</span></span>
<span class="line"><span style="color:#E1E4E8;">    transitionDuration</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> transitionDuration,</span></span>
<span class="line"><span style="color:#E1E4E8;">    transitionBuilder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> transitionBuilder,</span></span>
<span class="line"><span style="color:#E1E4E8;">    settings</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> routeSettings,</span></span>
<span class="line"><span style="color:#E1E4E8;">  ));</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">showGeneralDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">extends</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Object</span><span style="color:#24292E;">?&gt;({</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">RoutePageBuilder</span><span style="color:#24292E;"> pageBuilder,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> barrierDismissible </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">false</span><span style="color:#24292E;">,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">String</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> barrierLabel,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Color</span><span style="color:#24292E;"> barrierColor </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Color</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">0x80000000</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Duration</span><span style="color:#24292E;"> transitionDuration </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Duration</span><span style="color:#24292E;">(milliseconds</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">200</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">RouteTransitionsBuilder</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> transitionBuilder,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> useRootNavigator </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">true</span><span style="color:#24292E;">,</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">RouteSettings</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> routeSettings,</span></span>
<span class="line"><span style="color:#24292E;">}) {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context, rootNavigator</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> useRootNavigator).</span><span style="color:#6F42C1;">push</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;">&gt;(</span><span style="color:#005CC5;">RawDialogRoute</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">T</span><span style="color:#24292E;">&gt;(</span></span>
<span class="line"><span style="color:#24292E;">    pageBuilder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> pageBuilder,</span></span>
<span class="line"><span style="color:#24292E;">    barrierDismissible</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> barrierDismissible,</span></span>
<span class="line"><span style="color:#24292E;">    barrierLabel</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> barrierLabel,</span></span>
<span class="line"><span style="color:#24292E;">    barrierColor</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> barrierColor,</span></span>
<span class="line"><span style="color:#24292E;">    transitionDuration</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> transitionDuration,</span></span>
<span class="line"><span style="color:#24292E;">    transitionBuilder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> transitionBuilder,</span></span>
<span class="line"><span style="color:#24292E;">    settings</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> routeSettings,</span></span>
<span class="line"><span style="color:#24292E;">  ));</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>实现很简单，直接调用<code>Navigator</code>的<code>push</code>方法打开了一个新的对话框路由<code>RawDialogRoute</code>，然后返回了<code>push</code>的返回值。可见对话框实际上正是通过路由的形式实现的，这也是为什么我们可以使用<code>Navigator</code>的<code>pop</code> 方法来退出对话框的原因。关于对话框的样式定制在<code>RawDialogRoute</code>中，没有什么新的东西，读者可以自行查看。</p><h2 id="_7-7-4-对话框状态管理" tabindex="-1">7.7.4 对话框状态管理 <a class="header-anchor" href="#_7-7-4-对话框状态管理" aria-label="Permalink to &quot;7.7.4 对话框状态管理&quot;">​</a></h2><p>我们在用户选择删除一个文件时，会询问是否删除此文件；在用户选择一个文件夹是，应该再让用户确认是否删除子文件夹。为了在用户选择了文件夹时避免二次弹窗确认是否删除子目录，我们在确认对话框底部添加一个“同时删除子目录？”的复选框，如图7-15所示：</p><p><img src="/assets/7-15.580d6283.png" alt="图7-15"></p><p>现在就有一个问题：如何管理复选框的选中状态？习惯上，我们会在路由页的State中来管理选中状态，我们可能会写出如下这样的代码：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#F97583;">class</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">_DialogRouteState</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">extends</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">State</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">DialogRoute</span><span style="color:#E1E4E8;">&gt; {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> withTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">false</span><span style="color:#E1E4E8;">; </span><span style="color:#6A737D;">// 复选框选中状态</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">@override</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Widget</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">build</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Column</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#79B8FF;">ElevatedButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;对话框2&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">          onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">async</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">bool</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> delete </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">await</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDeleteConfirmDialog2</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#F97583;">if</span><span style="color:#E1E4E8;"> (delete </span><span style="color:#F97583;">==</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">null</span><span style="color:#E1E4E8;">) {</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;取消删除&quot;</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">            } </span><span style="color:#F97583;">else</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;同时删除子目录: $</span><span style="color:#79B8FF;">delete</span><span style="color:#9ECBFF;">&quot;</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">            }</span></span>
<span class="line"><span style="color:#E1E4E8;">          },</span></span>
<span class="line"><span style="color:#E1E4E8;">        ),</span></span>
<span class="line"><span style="color:#E1E4E8;">      ],</span></span>
<span class="line"><span style="color:#E1E4E8;">    );</span></span>
<span class="line"><span style="color:#E1E4E8;">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">showDeleteConfirmDialog2</span><span style="color:#E1E4E8;">() {</span></span>
<span class="line"><span style="color:#E1E4E8;">    withTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">false</span><span style="color:#E1E4E8;">; </span><span style="color:#6A737D;">// 默认复选框不选中</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">&gt;(</span></span>
<span class="line"><span style="color:#E1E4E8;">      context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">      builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;提示&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">          content</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Column</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            crossAxisAlignment</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">CrossAxisAlignment</span><span style="color:#E1E4E8;">.start,</span></span>
<span class="line"><span style="color:#E1E4E8;">            mainAxisSize</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">MainAxisSize</span><span style="color:#E1E4E8;">.min,</span></span>
<span class="line"><span style="color:#E1E4E8;">            children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#79B8FF;">Row</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">                children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">                  </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;同时删除子目录？&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">                  </span><span style="color:#79B8FF;">Checkbox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">                    value</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> withTree,</span></span>
<span class="line"><span style="color:#E1E4E8;">                    onChanged</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> value) {</span></span>
<span class="line"><span style="color:#E1E4E8;">                      </span><span style="color:#6A737D;">//复选框选中状态发生变化时重新构建UI</span></span>
<span class="line"><span style="color:#E1E4E8;">                      </span><span style="color:#B392F0;">setState</span><span style="color:#E1E4E8;">(() {</span></span>
<span class="line"><span style="color:#E1E4E8;">                        </span><span style="color:#6A737D;">//更新复选框状态</span></span>
<span class="line"><span style="color:#E1E4E8;">                        withTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">!</span><span style="color:#E1E4E8;">withTree;</span></span>
<span class="line"><span style="color:#E1E4E8;">                      });</span></span>
<span class="line"><span style="color:#E1E4E8;">                    },</span></span>
<span class="line"><span style="color:#E1E4E8;">                  ),</span></span>
<span class="line"><span style="color:#E1E4E8;">                ],</span></span>
<span class="line"><span style="color:#E1E4E8;">              ),</span></span>
<span class="line"><span style="color:#E1E4E8;">            ],</span></span>
<span class="line"><span style="color:#E1E4E8;">          ),</span></span>
<span class="line"><span style="color:#E1E4E8;">          actions</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">              child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;取消&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">              onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(),</span></span>
<span class="line"><span style="color:#E1E4E8;">            ),</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">              child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;删除&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">              onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () {</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#6A737D;">//执行删除操作</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(withTree);</span></span>
<span class="line"><span style="color:#E1E4E8;">              },</span></span>
<span class="line"><span style="color:#E1E4E8;">            ),</span></span>
<span class="line"><span style="color:#E1E4E8;">          ],</span></span>
<span class="line"><span style="color:#E1E4E8;">        );</span></span>
<span class="line"><span style="color:#E1E4E8;">      },</span></span>
<span class="line"><span style="color:#E1E4E8;">    );</span></span>
<span class="line"><span style="color:#E1E4E8;">  }</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#D73A49;">class</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">_DialogRouteState</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">extends</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">State</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">DialogRoute</span><span style="color:#24292E;">&gt; {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> withTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">false</span><span style="color:#24292E;">; </span><span style="color:#6A737D;">// 复选框选中状态</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">@override</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Widget</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">build</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context) {</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Column</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#005CC5;">ElevatedButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;对话框2&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">          onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">async</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">bool</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> delete </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">await</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDeleteConfirmDialog2</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#D73A49;">if</span><span style="color:#24292E;"> (delete </span><span style="color:#D73A49;">==</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">null</span><span style="color:#24292E;">) {</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;取消删除&quot;</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">            } </span><span style="color:#D73A49;">else</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;同时删除子目录: $</span><span style="color:#005CC5;">delete</span><span style="color:#032F62;">&quot;</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">            }</span></span>
<span class="line"><span style="color:#24292E;">          },</span></span>
<span class="line"><span style="color:#24292E;">        ),</span></span>
<span class="line"><span style="color:#24292E;">      ],</span></span>
<span class="line"><span style="color:#24292E;">    );</span></span>
<span class="line"><span style="color:#24292E;">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">showDeleteConfirmDialog2</span><span style="color:#24292E;">() {</span></span>
<span class="line"><span style="color:#24292E;">    withTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">false</span><span style="color:#24292E;">; </span><span style="color:#6A737D;">// 默认复选框不选中</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">&gt;(</span></span>
<span class="line"><span style="color:#24292E;">      context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">      builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (context) {</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;提示&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">          content</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Column</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            crossAxisAlignment</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">CrossAxisAlignment</span><span style="color:#24292E;">.start,</span></span>
<span class="line"><span style="color:#24292E;">            mainAxisSize</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">MainAxisSize</span><span style="color:#24292E;">.min,</span></span>
<span class="line"><span style="color:#24292E;">            children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#005CC5;">Row</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">                children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">                  </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;同时删除子目录？&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">                  </span><span style="color:#005CC5;">Checkbox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">                    value</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> withTree,</span></span>
<span class="line"><span style="color:#24292E;">                    onChanged</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> value) {</span></span>
<span class="line"><span style="color:#24292E;">                      </span><span style="color:#6A737D;">//复选框选中状态发生变化时重新构建UI</span></span>
<span class="line"><span style="color:#24292E;">                      </span><span style="color:#6F42C1;">setState</span><span style="color:#24292E;">(() {</span></span>
<span class="line"><span style="color:#24292E;">                        </span><span style="color:#6A737D;">//更新复选框状态</span></span>
<span class="line"><span style="color:#24292E;">                        withTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">!</span><span style="color:#24292E;">withTree;</span></span>
<span class="line"><span style="color:#24292E;">                      });</span></span>
<span class="line"><span style="color:#24292E;">                    },</span></span>
<span class="line"><span style="color:#24292E;">                  ),</span></span>
<span class="line"><span style="color:#24292E;">                ],</span></span>
<span class="line"><span style="color:#24292E;">              ),</span></span>
<span class="line"><span style="color:#24292E;">            ],</span></span>
<span class="line"><span style="color:#24292E;">          ),</span></span>
<span class="line"><span style="color:#24292E;">          actions</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">              child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;取消&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">              onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(),</span></span>
<span class="line"><span style="color:#24292E;">            ),</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">              child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;删除&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">              onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () {</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#6A737D;">//执行删除操作</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(withTree);</span></span>
<span class="line"><span style="color:#24292E;">              },</span></span>
<span class="line"><span style="color:#24292E;">            ),</span></span>
<span class="line"><span style="color:#24292E;">          ],</span></span>
<span class="line"><span style="color:#24292E;">        );</span></span>
<span class="line"><span style="color:#24292E;">      },</span></span>
<span class="line"><span style="color:#24292E;">    );</span></span>
<span class="line"><span style="color:#24292E;">  }</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>然后，当我们运行上面的代码时我们会发现复选框根本选不中！为什么会这样呢？其实原因很简单，我们知道<code>setState</code>方法只会针对当前context的子树重新build，但是我们的对话框并不是在<code>_DialogRouteState</code>的<code>build</code> 方法中构建的，而是通过<code>showDialog</code>单独构建的，所以在<code>_DialogRouteState</code>的context中调用<code>setState</code>是无法影响通过<code>showDialog</code>构建的UI的。另外，我们可以从另外一个角度来理解这个现象，前面说过对话框也是通过路由的方式来实现的，那么上面的代码实际上就等同于企图在父路由中调用<code>setState</code>来让子路由更新，这显然是不行的！简尔言之，根本原因就是context不对。那如何让复选框可点击呢？通常有如下三种方法：</p><h3 id="_1-单独抽离出statefulwidget" tabindex="-1">1. 单独抽离出StatefulWidget <a class="header-anchor" href="#_1-单独抽离出statefulwidget" aria-label="Permalink to &quot;1. 单独抽离出StatefulWidget&quot;">​</a></h3><p>既然是context不对，那么直接的思路就是将复选框的选中逻辑单独封装成一个<code>StatefulWidget</code>，然后在其内部管理复选状态。我们先来看看这种方法，下面是实现代码：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#6A737D;">// 单独封装一个内部管理选中状态的复选框组件</span></span>
<span class="line"><span style="color:#F97583;">class</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">DialogCheckbox</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">extends</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">StatefulWidget</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">DialogCheckbox</span><span style="color:#E1E4E8;">({</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">Key</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> key,</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.value,</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.onChanged,</span></span>
<span class="line"><span style="color:#E1E4E8;">  });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">final</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ValueChanged</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">?&gt; onChanged;</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">final</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">bool</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> value;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">@override</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">_DialogCheckboxState</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">createState</span><span style="color:#E1E4E8;">() </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">_DialogCheckboxState</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583;">class</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">_DialogCheckboxState</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">extends</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">State</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">DialogCheckbox</span><span style="color:#E1E4E8;">&gt; {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">bool</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> value;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">@override</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">void</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">initState</span><span style="color:#E1E4E8;">() {</span></span>
<span class="line"><span style="color:#E1E4E8;">    value </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> widget.value;</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">super</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">initState</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">@override</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Widget</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">build</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Checkbox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      value</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> value,</span></span>
<span class="line"><span style="color:#E1E4E8;">      onChanged</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (v) {</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#6A737D;">//将选中状态通过事件的形式抛出</span></span>
<span class="line"><span style="color:#E1E4E8;">        widget.</span><span style="color:#B392F0;">onChanged</span><span style="color:#E1E4E8;">(v);</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#B392F0;">setState</span><span style="color:#E1E4E8;">(() {</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#6A737D;">//更新自身选中状态</span></span>
<span class="line"><span style="color:#E1E4E8;">          value </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> v;</span></span>
<span class="line"><span style="color:#E1E4E8;">        });</span></span>
<span class="line"><span style="color:#E1E4E8;">      },</span></span>
<span class="line"><span style="color:#E1E4E8;">    );</span></span>
<span class="line"><span style="color:#E1E4E8;">  }</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#6A737D;">// 单独封装一个内部管理选中状态的复选框组件</span></span>
<span class="line"><span style="color:#D73A49;">class</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">DialogCheckbox</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">extends</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">StatefulWidget</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">DialogCheckbox</span><span style="color:#24292E;">({</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">Key</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> key,</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.value,</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.onChanged,</span></span>
<span class="line"><span style="color:#24292E;">  });</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">final</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ValueChanged</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">?&gt; onChanged;</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">final</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">bool</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> value;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">@override</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">_DialogCheckboxState</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">createState</span><span style="color:#24292E;">() </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">_DialogCheckboxState</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#D73A49;">class</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">_DialogCheckboxState</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">extends</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">State</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">DialogCheckbox</span><span style="color:#24292E;">&gt; {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">bool</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> value;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">@override</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">void</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">initState</span><span style="color:#24292E;">() {</span></span>
<span class="line"><span style="color:#24292E;">    value </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> widget.value;</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">super</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">initState</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">@override</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Widget</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">build</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context) {</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Checkbox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      value</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> value,</span></span>
<span class="line"><span style="color:#24292E;">      onChanged</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (v) {</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#6A737D;">//将选中状态通过事件的形式抛出</span></span>
<span class="line"><span style="color:#24292E;">        widget.</span><span style="color:#6F42C1;">onChanged</span><span style="color:#24292E;">(v);</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#6F42C1;">setState</span><span style="color:#24292E;">(() {</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#6A737D;">//更新自身选中状态</span></span>
<span class="line"><span style="color:#24292E;">          value </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> v;</span></span>
<span class="line"><span style="color:#24292E;">        });</span></span>
<span class="line"><span style="color:#24292E;">      },</span></span>
<span class="line"><span style="color:#24292E;">    );</span></span>
<span class="line"><span style="color:#24292E;">  }</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>下面是弹出对话框的代码：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">showDeleteConfirmDialog3</span><span style="color:#E1E4E8;">() {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> _withTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">false</span><span style="color:#E1E4E8;">; </span><span style="color:#6A737D;">//记录复选框是否选中</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">&gt;(</span></span>
<span class="line"><span style="color:#E1E4E8;">    context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">        title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;提示&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">        content</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Column</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          crossAxisAlignment</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">CrossAxisAlignment</span><span style="color:#E1E4E8;">.start,</span></span>
<span class="line"><span style="color:#E1E4E8;">          mainAxisSize</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">MainAxisSize</span><span style="color:#E1E4E8;">.min,</span></span>
<span class="line"><span style="color:#E1E4E8;">          children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">Row</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">              children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;同时删除子目录？&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#79B8FF;">DialogCheckbox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">                  value</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> _withTree, </span><span style="color:#6A737D;">//默认不选中</span></span>
<span class="line"><span style="color:#E1E4E8;">                  onChanged</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> value) {</span></span>
<span class="line"><span style="color:#E1E4E8;">                    </span><span style="color:#6A737D;">//更新选中状态</span></span>
<span class="line"><span style="color:#E1E4E8;">                    _withTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">!</span><span style="color:#E1E4E8;">_withTree;</span></span>
<span class="line"><span style="color:#E1E4E8;">                  },</span></span>
<span class="line"><span style="color:#E1E4E8;">                ),</span></span>
<span class="line"><span style="color:#E1E4E8;">              ],</span></span>
<span class="line"><span style="color:#E1E4E8;">            ),</span></span>
<span class="line"><span style="color:#E1E4E8;">          ],</span></span>
<span class="line"><span style="color:#E1E4E8;">        ),</span></span>
<span class="line"><span style="color:#E1E4E8;">        actions</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;取消&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(),</span></span>
<span class="line"><span style="color:#E1E4E8;">          ),</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;删除&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () {</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#6A737D;">// 将选中状态返回</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(_withTree);</span></span>
<span class="line"><span style="color:#E1E4E8;">            },</span></span>
<span class="line"><span style="color:#E1E4E8;">          ),</span></span>
<span class="line"><span style="color:#E1E4E8;">        ],</span></span>
<span class="line"><span style="color:#E1E4E8;">      );</span></span>
<span class="line"><span style="color:#E1E4E8;">    },</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">showDeleteConfirmDialog3</span><span style="color:#24292E;">() {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> _withTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">false</span><span style="color:#24292E;">; </span><span style="color:#6A737D;">//记录复选框是否选中</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">&gt;(</span></span>
<span class="line"><span style="color:#24292E;">    context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (context) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">        title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;提示&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">        content</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Column</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          crossAxisAlignment</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">CrossAxisAlignment</span><span style="color:#24292E;">.start,</span></span>
<span class="line"><span style="color:#24292E;">          mainAxisSize</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">MainAxisSize</span><span style="color:#24292E;">.min,</span></span>
<span class="line"><span style="color:#24292E;">          children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">Row</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">              children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;同时删除子目录？&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#005CC5;">DialogCheckbox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">                  value</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> _withTree, </span><span style="color:#6A737D;">//默认不选中</span></span>
<span class="line"><span style="color:#24292E;">                  onChanged</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> value) {</span></span>
<span class="line"><span style="color:#24292E;">                    </span><span style="color:#6A737D;">//更新选中状态</span></span>
<span class="line"><span style="color:#24292E;">                    _withTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">!</span><span style="color:#24292E;">_withTree;</span></span>
<span class="line"><span style="color:#24292E;">                  },</span></span>
<span class="line"><span style="color:#24292E;">                ),</span></span>
<span class="line"><span style="color:#24292E;">              ],</span></span>
<span class="line"><span style="color:#24292E;">            ),</span></span>
<span class="line"><span style="color:#24292E;">          ],</span></span>
<span class="line"><span style="color:#24292E;">        ),</span></span>
<span class="line"><span style="color:#24292E;">        actions</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;取消&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(),</span></span>
<span class="line"><span style="color:#24292E;">          ),</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;删除&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () {</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#6A737D;">// 将选中状态返回</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(_withTree);</span></span>
<span class="line"><span style="color:#24292E;">            },</span></span>
<span class="line"><span style="color:#24292E;">          ),</span></span>
<span class="line"><span style="color:#24292E;">        ],</span></span>
<span class="line"><span style="color:#24292E;">      );</span></span>
<span class="line"><span style="color:#24292E;">    },</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>最后，就是使用：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">ElevatedButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;话框3（复选框可点击）&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">  onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">async</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#6A737D;">//弹出删除确认对话框，等待用户确认</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">bool</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> deleteTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">await</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDeleteConfirmDialog3</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#F97583;">if</span><span style="color:#E1E4E8;"> (deleteTree </span><span style="color:#F97583;">==</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">null</span><span style="color:#E1E4E8;">) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;取消删除&quot;</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">    } </span><span style="color:#F97583;">else</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;同时删除子目录: $</span><span style="color:#79B8FF;">deleteTree</span><span style="color:#9ECBFF;">&quot;</span><span style="color:#E1E4E8;">);</span></span>
<span class="line"><span style="color:#E1E4E8;">    }</span></span>
<span class="line"><span style="color:#E1E4E8;">  },</span></span>
<span class="line"><span style="color:#E1E4E8;">),</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">ElevatedButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;话框3（复选框可点击）&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">  onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">async</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#6A737D;">//弹出删除确认对话框，等待用户确认</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">bool</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> deleteTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">await</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDeleteConfirmDialog3</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#D73A49;">if</span><span style="color:#24292E;"> (deleteTree </span><span style="color:#D73A49;">==</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">null</span><span style="color:#24292E;">) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;取消删除&quot;</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">    } </span><span style="color:#D73A49;">else</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;同时删除子目录: $</span><span style="color:#005CC5;">deleteTree</span><span style="color:#032F62;">&quot;</span><span style="color:#24292E;">);</span></span>
<span class="line"><span style="color:#24292E;">    }</span></span>
<span class="line"><span style="color:#24292E;">  },</span></span>
<span class="line"><span style="color:#24292E;">),</span></span></code></pre></div><p>运行后效果如图7-16所示：</p><p><img src="/assets/7-16.f021170c.png" alt="图7-16"></p><p>可见复选框能选中了，点击“取消”或“删除”后，控制台就会打印出最终的确认状态。</p><h3 id="_2-使用statefulbuilder方法" tabindex="-1">2. 使用StatefulBuilder方法 <a class="header-anchor" href="#_2-使用statefulbuilder方法" aria-label="Permalink to &quot;2. 使用StatefulBuilder方法&quot;">​</a></h3><p>上面的方法虽然能解决对话框状态更新的问题，但是有一个明显的缺点——对话框上所有可能会改变状态的组件都得单独封装在一个在内部管理状态的<code>StatefulWidget</code>中，这样不仅麻烦，而且复用性不大。因此，我们来想想能不能找到一种更简单的方法？上面的方法本质上就是将对话框的状态置于一个<code>StatefulWidget</code>的上下文中，由<code>StatefulWidget</code>在内部管理，那么我们有没有办法在不需要单独抽离组件的情况下创建一个<code>StatefulWidget</code>的上下文呢？想到这里，我们可以从<code>Builder</code>组件的实现获得灵感。在前面介绍过<code>Builder</code>组件可以获得组件所在位置的真正的Context，那它是怎么实现的呢，我们看看它的源码：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#F97583;">class</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Builder</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">extends</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">StatelessWidget</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Builder</span><span style="color:#E1E4E8;">({</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">Key</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> key,</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.builder,</span></span>
<span class="line"><span style="color:#E1E4E8;">  }) </span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">assert</span><span style="color:#E1E4E8;">(builder </span><span style="color:#F97583;">!=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">null</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">       </span><span style="color:#79B8FF;">super</span><span style="color:#E1E4E8;">(key</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> key);</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">final</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">WidgetBuilder</span><span style="color:#E1E4E8;"> builder;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">@override</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Widget</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">build</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context) </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">builder</span><span style="color:#E1E4E8;">(context);</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#D73A49;">class</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Builder</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">extends</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">StatelessWidget</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Builder</span><span style="color:#24292E;">({</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">Key</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> key,</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.builder,</span></span>
<span class="line"><span style="color:#24292E;">  }) </span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">assert</span><span style="color:#24292E;">(builder </span><span style="color:#D73A49;">!=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">null</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">       </span><span style="color:#005CC5;">super</span><span style="color:#24292E;">(key</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> key);</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">final</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">WidgetBuilder</span><span style="color:#24292E;"> builder;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">@override</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Widget</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">build</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context) </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">builder</span><span style="color:#24292E;">(context);</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>可以看到，<code>Builder</code>实际上只是继承了<code>StatelessWidget</code>，然后在<code>build</code>方法中获取当前context后将构建方法代理到了<code>builder</code>回调，可见，<code>Builder</code>实际上是获取了<code>StatelessWidget</code> 的上下文（context）。那么我们能否用相同的方法获取<code>StatefulWidget</code> 的上下文，并代理其<code>build</code>方法呢？下面我们照猫画虎，来封装一个<code>StatefulBuilder</code>方法：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#F97583;">class</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">StatefulBuilder</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">extends</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">StatefulWidget</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">StatefulBuilder</span><span style="color:#E1E4E8;">({</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">Key</span><span style="color:#F97583;">?</span><span style="color:#E1E4E8;"> key,</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#F97583;">required</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">this</span><span style="color:#E1E4E8;">.builder,</span></span>
<span class="line"><span style="color:#E1E4E8;">  }) </span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">assert</span><span style="color:#E1E4E8;">(builder </span><span style="color:#F97583;">!=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">null</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">       </span><span style="color:#79B8FF;">super</span><span style="color:#E1E4E8;">(key</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> key);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">final</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">StatefulWidgetBuilder</span><span style="color:#E1E4E8;"> builder;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">@override</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">_StatefulBuilderState</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">createState</span><span style="color:#E1E4E8;">() </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">_StatefulBuilderState</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583;">class</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">_StatefulBuilderState</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">extends</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">State</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">StatefulBuilder</span><span style="color:#E1E4E8;">&gt; {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">@override</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">Widget</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">build</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context) </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> widget.</span><span style="color:#B392F0;">builder</span><span style="color:#E1E4E8;">(context, setState);</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#D73A49;">class</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">StatefulBuilder</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">extends</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">StatefulWidget</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">StatefulBuilder</span><span style="color:#24292E;">({</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">Key</span><span style="color:#D73A49;">?</span><span style="color:#24292E;"> key,</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#D73A49;">required</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">this</span><span style="color:#24292E;">.builder,</span></span>
<span class="line"><span style="color:#24292E;">  }) </span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">assert</span><span style="color:#24292E;">(builder </span><span style="color:#D73A49;">!=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">null</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">       </span><span style="color:#005CC5;">super</span><span style="color:#24292E;">(key</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> key);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">final</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">StatefulWidgetBuilder</span><span style="color:#24292E;"> builder;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">@override</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">_StatefulBuilderState</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">createState</span><span style="color:#24292E;">() </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">_StatefulBuilderState</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#D73A49;">class</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">_StatefulBuilderState</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">extends</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">State</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">StatefulBuilder</span><span style="color:#24292E;">&gt; {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">@override</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">Widget</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">build</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context) </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> widget.</span><span style="color:#6F42C1;">builder</span><span style="color:#24292E;">(context, setState);</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>代码很简单，<code>StatefulBuilder</code>获取了<code>StatefulWidget</code>的上下文，并代理了其构建过程。下面我们就可以通过<code>StatefulBuilder</code>来重构上面的代码了（变动只在<code>DialogCheckbox</code>部分）：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#E1E4E8;">... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#79B8FF;">Row</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;同时删除子目录？&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#6A737D;">//使用StatefulBuilder来构建StatefulWidget上下文</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">StatefulBuilder</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (context, _setState) {</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Checkbox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          value</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> _withTree, </span><span style="color:#6A737D;">//默认不选中</span></span>
<span class="line"><span style="color:#E1E4E8;">          onChanged</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> value) {</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#6A737D;">//_setState方法实际就是该StatefulWidget的setState方法，</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#6A737D;">//调用后builder方法会重新被调用</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#B392F0;">_setState</span><span style="color:#E1E4E8;">(() {</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#6A737D;">//更新选中状态</span></span>
<span class="line"><span style="color:#E1E4E8;">              _withTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">!</span><span style="color:#E1E4E8;">_withTree;</span></span>
<span class="line"><span style="color:#E1E4E8;">            });</span></span>
<span class="line"><span style="color:#E1E4E8;">          },</span></span>
<span class="line"><span style="color:#E1E4E8;">        );</span></span>
<span class="line"><span style="color:#E1E4E8;">      },</span></span>
<span class="line"><span style="color:#E1E4E8;">    ),</span></span>
<span class="line"><span style="color:#E1E4E8;">  ],</span></span>
<span class="line"><span style="color:#E1E4E8;">),</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#24292E;">... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#005CC5;">Row</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;同时删除子目录？&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#6A737D;">//使用StatefulBuilder来构建StatefulWidget上下文</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">StatefulBuilder</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (context, _setState) {</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Checkbox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          value</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> _withTree, </span><span style="color:#6A737D;">//默认不选中</span></span>
<span class="line"><span style="color:#24292E;">          onChanged</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> value) {</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#6A737D;">//_setState方法实际就是该StatefulWidget的setState方法，</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#6A737D;">//调用后builder方法会重新被调用</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#6F42C1;">_setState</span><span style="color:#24292E;">(() {</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#6A737D;">//更新选中状态</span></span>
<span class="line"><span style="color:#24292E;">              _withTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">!</span><span style="color:#24292E;">_withTree;</span></span>
<span class="line"><span style="color:#24292E;">            });</span></span>
<span class="line"><span style="color:#24292E;">          },</span></span>
<span class="line"><span style="color:#24292E;">        );</span></span>
<span class="line"><span style="color:#24292E;">      },</span></span>
<span class="line"><span style="color:#24292E;">    ),</span></span>
<span class="line"><span style="color:#24292E;">  ],</span></span>
<span class="line"><span style="color:#24292E;">),</span></span></code></pre></div><p>实际上，这种方法本质上就是子组件通知父组件（StatefulWidget）重新build子组件本身来实现UI更新的，读者可以对比代码理解。实际上<code>StatefulBuilder</code>正是Flutter SDK中提供的一个类，它和<code>Builder</code>的原理是一样的，在此，提醒读者一定要将<code>StatefulBuilder</code>和<code>Builder</code>理解透彻，因为它们在Flutter中是非常实用的。</p><h3 id="_3-精妙的解法" tabindex="-1">3. 精妙的解法 <a class="header-anchor" href="#_3-精妙的解法" aria-label="Permalink to &quot;3. 精妙的解法&quot;">​</a></h3><p>是否还有更简单的解决方案呢？要确认这个问题，我们就得先搞清楚UI是怎么更新的，我们知道在调用<code>setState</code>方法后<code>StatefulWidget</code>就会重新build，那<code>setState</code>方法做了什么呢？我们能不能从中找到方法？顺着这个思路，我们就得看一下<code>setState</code>的核心源码：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#F97583;">void</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">setState</span><span style="color:#E1E4E8;">(</span><span style="color:#79B8FF;">VoidCallback</span><span style="color:#E1E4E8;"> fn) {</span></span>
<span class="line"><span style="color:#E1E4E8;">  ... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#E1E4E8;">  _element.</span><span style="color:#B392F0;">markNeedsBuild</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#D73A49;">void</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">setState</span><span style="color:#24292E;">(</span><span style="color:#005CC5;">VoidCallback</span><span style="color:#24292E;"> fn) {</span></span>
<span class="line"><span style="color:#24292E;">  ... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#24292E;">  _element.</span><span style="color:#6F42C1;">markNeedsBuild</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>可以发现，<code>setState</code>中调用了<code>Element</code>的<code>markNeedsBuild()</code>方法，我们前面说过，Flutter是一个响应式框架，要更新UI只需改变状态后通知框架页面需要重构即可，而<code>Element</code>的<code>markNeedsBuild()</code>方法正是来实现这个功能的！<code>markNeedsBuild()</code>方法会将当前的<code>Element</code>对象标记为“dirty”（脏的），在每一个Frame，Flutter都会重新构建被标记为“dirty”<code>Element</code>对象。既然如此，我们有没有办法获取到对话框内部UI的<code>Element</code>对象，然后将其标示为为“dirty”呢？答案是肯定的！我们可以通过Context来得到<code>Element</code>对象，至于<code>Element</code>与<code>Context</code>的关系我们将会在后面“Flutter核心原理”一章中再深入介绍，现在只需要简单的认为：在组件树中，<code>context</code>实际上就是<code>Element</code>对象的引用。知道这个后，那么解决的方案就呼之欲出了，我们可以通过如下方式来让复选框可以更新：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">showDeleteConfirmDialog4</span><span style="color:#E1E4E8;">() {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> _withTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">false</span><span style="color:#E1E4E8;">;</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDialog</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;">&gt;(</span></span>
<span class="line"><span style="color:#E1E4E8;">    context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">        title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;提示&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">        content</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Column</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          crossAxisAlignment</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">CrossAxisAlignment</span><span style="color:#E1E4E8;">.start,</span></span>
<span class="line"><span style="color:#E1E4E8;">          mainAxisSize</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">MainAxisSize</span><span style="color:#E1E4E8;">.min,</span></span>
<span class="line"><span style="color:#E1E4E8;">          children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">Row</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">              children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;同时删除子目录？&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">                </span><span style="color:#79B8FF;">Checkbox</span><span style="color:#E1E4E8;">( </span><span style="color:#6A737D;">// 依然使用Checkbox组件</span></span>
<span class="line"><span style="color:#E1E4E8;">                  value</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> _withTree,</span></span>
<span class="line"><span style="color:#E1E4E8;">                  onChanged</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> value) {</span></span>
<span class="line"><span style="color:#E1E4E8;">                    </span><span style="color:#6A737D;">// 此时context为对话框UI的根Element，我们 </span></span>
<span class="line"><span style="color:#E1E4E8;">                    </span><span style="color:#6A737D;">// 直接将对话框UI对应的Element标记为dirty</span></span>
<span class="line"><span style="color:#E1E4E8;">                    (context </span><span style="color:#F97583;">as</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Element</span><span style="color:#E1E4E8;">).</span><span style="color:#B392F0;">markNeedsBuild</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">                    _withTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">!</span><span style="color:#E1E4E8;">_withTree;</span></span>
<span class="line"><span style="color:#E1E4E8;">                  },</span></span>
<span class="line"><span style="color:#E1E4E8;">                ),</span></span>
<span class="line"><span style="color:#E1E4E8;">              ],</span></span>
<span class="line"><span style="color:#E1E4E8;">            ),</span></span>
<span class="line"><span style="color:#E1E4E8;">          ],</span></span>
<span class="line"><span style="color:#E1E4E8;">        ),</span></span>
<span class="line"><span style="color:#E1E4E8;">        actions</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;取消&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(),</span></span>
<span class="line"><span style="color:#E1E4E8;">          ),</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">TextButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;删除&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () {</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#6A737D;">// 执行删除操作</span></span>
<span class="line"><span style="color:#E1E4E8;">              </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(_withTree);</span></span>
<span class="line"><span style="color:#E1E4E8;">            },</span></span>
<span class="line"><span style="color:#E1E4E8;">          ),</span></span>
<span class="line"><span style="color:#E1E4E8;">        ],</span></span>
<span class="line"><span style="color:#E1E4E8;">      );</span></span>
<span class="line"><span style="color:#E1E4E8;">    },</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">showDeleteConfirmDialog4</span><span style="color:#24292E;">() {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> _withTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">false</span><span style="color:#24292E;">;</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDialog</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;">&gt;(</span></span>
<span class="line"><span style="color:#24292E;">    context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (context) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">        title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;提示&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">        content</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Column</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          crossAxisAlignment</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">CrossAxisAlignment</span><span style="color:#24292E;">.start,</span></span>
<span class="line"><span style="color:#24292E;">          mainAxisSize</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">MainAxisSize</span><span style="color:#24292E;">.min,</span></span>
<span class="line"><span style="color:#24292E;">          children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;您确定要删除当前文件吗?&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">Row</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">              children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;同时删除子目录？&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">                </span><span style="color:#005CC5;">Checkbox</span><span style="color:#24292E;">( </span><span style="color:#6A737D;">// 依然使用Checkbox组件</span></span>
<span class="line"><span style="color:#24292E;">                  value</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> _withTree,</span></span>
<span class="line"><span style="color:#24292E;">                  onChanged</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> value) {</span></span>
<span class="line"><span style="color:#24292E;">                    </span><span style="color:#6A737D;">// 此时context为对话框UI的根Element，我们 </span></span>
<span class="line"><span style="color:#24292E;">                    </span><span style="color:#6A737D;">// 直接将对话框UI对应的Element标记为dirty</span></span>
<span class="line"><span style="color:#24292E;">                    (context </span><span style="color:#D73A49;">as</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Element</span><span style="color:#24292E;">).</span><span style="color:#6F42C1;">markNeedsBuild</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">                    _withTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">!</span><span style="color:#24292E;">_withTree;</span></span>
<span class="line"><span style="color:#24292E;">                  },</span></span>
<span class="line"><span style="color:#24292E;">                ),</span></span>
<span class="line"><span style="color:#24292E;">              ],</span></span>
<span class="line"><span style="color:#24292E;">            ),</span></span>
<span class="line"><span style="color:#24292E;">          ],</span></span>
<span class="line"><span style="color:#24292E;">        ),</span></span>
<span class="line"><span style="color:#24292E;">        actions</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;取消&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(),</span></span>
<span class="line"><span style="color:#24292E;">          ),</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">TextButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;删除&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () {</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#6A737D;">// 执行删除操作</span></span>
<span class="line"><span style="color:#24292E;">              </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(_withTree);</span></span>
<span class="line"><span style="color:#24292E;">            },</span></span>
<span class="line"><span style="color:#24292E;">          ),</span></span>
<span class="line"><span style="color:#24292E;">        ],</span></span>
<span class="line"><span style="color:#24292E;">      );</span></span>
<span class="line"><span style="color:#24292E;">    },</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>上面的代码运行后复选框也可以正常选中。可以看到，我们只用了一行代码便解决了这个问题！当然上面的代码并不是最优，因为我们只需要更新复选框的状态，而此时的<code>context</code>我们用的是对话框的根<code>context</code>，所以会导致整个对话框UI组件全部rebuild，因此最好的做法是将<code>context</code>的“范围”缩小，也就是说只将<code>Checkbox</code>的Element标记为<code>dirty</code>，优化后的代码为：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#E1E4E8;">... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#79B8FF;">Row</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;同时删除子目录？&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#6A737D;">// 通过Builder来获得构建Checkbox的`context`，</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#6A737D;">// 这是一种常用的缩小`context`范围的方式</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">Builder</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">        </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Checkbox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          value</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> _withTree,</span></span>
<span class="line"><span style="color:#E1E4E8;">          onChanged</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">bool</span><span style="color:#E1E4E8;"> value) {</span></span>
<span class="line"><span style="color:#E1E4E8;">            (context </span><span style="color:#F97583;">as</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Element</span><span style="color:#E1E4E8;">).</span><span style="color:#B392F0;">markNeedsBuild</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">            _withTree </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">!</span><span style="color:#E1E4E8;">_withTree;</span></span>
<span class="line"><span style="color:#E1E4E8;">          },</span></span>
<span class="line"><span style="color:#E1E4E8;">        );</span></span>
<span class="line"><span style="color:#E1E4E8;">      },</span></span>
<span class="line"><span style="color:#E1E4E8;">    ),</span></span>
<span class="line"><span style="color:#E1E4E8;">  ],</span></span>
<span class="line"><span style="color:#E1E4E8;">),</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#24292E;">... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#005CC5;">Row</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;同时删除子目录？&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#6A737D;">// 通过Builder来获得构建Checkbox的`context`，</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#6A737D;">// 这是一种常用的缩小`context`范围的方式</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">Builder</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context) {</span></span>
<span class="line"><span style="color:#24292E;">        </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Checkbox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          value</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> _withTree,</span></span>
<span class="line"><span style="color:#24292E;">          onChanged</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">bool</span><span style="color:#24292E;"> value) {</span></span>
<span class="line"><span style="color:#24292E;">            (context </span><span style="color:#D73A49;">as</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Element</span><span style="color:#24292E;">).</span><span style="color:#6F42C1;">markNeedsBuild</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">            _withTree </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">!</span><span style="color:#24292E;">_withTree;</span></span>
<span class="line"><span style="color:#24292E;">          },</span></span>
<span class="line"><span style="color:#24292E;">        );</span></span>
<span class="line"><span style="color:#24292E;">      },</span></span>
<span class="line"><span style="color:#24292E;">    ),</span></span>
<span class="line"><span style="color:#24292E;">  ],</span></span>
<span class="line"><span style="color:#24292E;">),</span></span></code></pre></div><h2 id="_7-7-5-其他类型的对话框" tabindex="-1">7.7.5 其他类型的对话框 <a class="header-anchor" href="#_7-7-5-其他类型的对话框" aria-label="Permalink to &quot;7.7.5 其他类型的对话框&quot;">​</a></h2><h3 id="_1-底部菜单列表" tabindex="-1">1. 底部菜单列表 <a class="header-anchor" href="#_1-底部菜单列表" aria-label="Permalink to &quot;1. 底部菜单列表&quot;">​</a></h3><p><code>showModalBottomSheet</code>方法可以弹出一个Material风格的底部菜单列表模态对话框，示例如下：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#6A737D;">// 弹出底部菜单列表模态对话框</span></span>
<span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">int</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">_showModalBottomSheet</span><span style="color:#E1E4E8;">() {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showModalBottomSheet</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">int</span><span style="color:#E1E4E8;">&gt;(</span></span>
<span class="line"><span style="color:#E1E4E8;">    context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ListView</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">builder</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">        itemCount</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">30</span><span style="color:#E1E4E8;">,</span></span>
<span class="line"><span style="color:#E1E4E8;">        itemBuilder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">BuildContext</span><span style="color:#E1E4E8;"> context, </span><span style="color:#79B8FF;">int</span><span style="color:#E1E4E8;"> index) {</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">ListTile</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            title</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;$</span><span style="color:#79B8FF;">index</span><span style="color:#9ECBFF;">&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            onTap</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">=&gt;</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Navigator</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">of</span><span style="color:#E1E4E8;">(context).</span><span style="color:#B392F0;">pop</span><span style="color:#E1E4E8;">(index),</span></span>
<span class="line"><span style="color:#E1E4E8;">          );</span></span>
<span class="line"><span style="color:#E1E4E8;">        },</span></span>
<span class="line"><span style="color:#E1E4E8;">      );</span></span>
<span class="line"><span style="color:#E1E4E8;">    },</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#6A737D;">// 弹出底部菜单列表模态对话框</span></span>
<span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">int</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">_showModalBottomSheet</span><span style="color:#24292E;">() {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showModalBottomSheet</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">int</span><span style="color:#24292E;">&gt;(</span></span>
<span class="line"><span style="color:#24292E;">    context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ListView</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">builder</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">        itemCount</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">30</span><span style="color:#24292E;">,</span></span>
<span class="line"><span style="color:#24292E;">        itemBuilder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">BuildContext</span><span style="color:#24292E;"> context, </span><span style="color:#005CC5;">int</span><span style="color:#24292E;"> index) {</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">ListTile</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            title</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;$</span><span style="color:#005CC5;">index</span><span style="color:#032F62;">&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            onTap</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">=&gt;</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Navigator</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">of</span><span style="color:#24292E;">(context).</span><span style="color:#6F42C1;">pop</span><span style="color:#24292E;">(index),</span></span>
<span class="line"><span style="color:#24292E;">          );</span></span>
<span class="line"><span style="color:#24292E;">        },</span></span>
<span class="line"><span style="color:#24292E;">      );</span></span>
<span class="line"><span style="color:#24292E;">    },</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>点击按钮，弹出该对话框：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">ElevatedButton</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;显示底部菜单列表&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">  onPressed</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> () </span><span style="color:#F97583;">async</span><span style="color:#E1E4E8;"> {</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#79B8FF;">int</span><span style="color:#E1E4E8;"> type </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">await</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">_showModalBottomSheet</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">    </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(type);</span></span>
<span class="line"><span style="color:#E1E4E8;">  },</span></span>
<span class="line"><span style="color:#E1E4E8;">),</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">ElevatedButton</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;显示底部菜单列表&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">  onPressed</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> () </span><span style="color:#D73A49;">async</span><span style="color:#24292E;"> {</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#005CC5;">int</span><span style="color:#24292E;"> type </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">await</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">_showModalBottomSheet</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">    </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(type);</span></span>
<span class="line"><span style="color:#24292E;">  },</span></span>
<span class="line"><span style="color:#24292E;">),</span></span></code></pre></div><p>运行后效果如图7-17所示：</p><p><img src="/assets/7-17.2983a410.png" alt="图7-17"></p><h3 id="_2-loading框" tabindex="-1">2. Loading框 <a class="header-anchor" href="#_2-loading框" aria-label="Permalink to &quot;2. Loading框&quot;">​</a></h3><p>其实Loading框可以直接通过<code>showDialog</code>+<code>AlertDialog</code>来自定义：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#B392F0;">showLoadingDialog</span><span style="color:#E1E4E8;">() {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#B392F0;">showDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    barrierDismissible</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">false</span><span style="color:#E1E4E8;">, </span><span style="color:#6A737D;">//点击遮罩不关闭对话框</span></span>
<span class="line"><span style="color:#E1E4E8;">    builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (context) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">        content</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Column</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          mainAxisSize</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">MainAxisSize</span><span style="color:#E1E4E8;">.min,</span></span>
<span class="line"><span style="color:#E1E4E8;">          children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">CircularProgressIndicator</span><span style="color:#E1E4E8;">(),</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">Padding</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">              padding</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">EdgeInsets</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">only</span><span style="color:#E1E4E8;">(top</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">26.0</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">              child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;正在加载，请稍后...&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            )</span></span>
<span class="line"><span style="color:#E1E4E8;">          ],</span></span>
<span class="line"><span style="color:#E1E4E8;">        ),</span></span>
<span class="line"><span style="color:#E1E4E8;">      );</span></span>
<span class="line"><span style="color:#E1E4E8;">    },</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#6F42C1;">showLoadingDialog</span><span style="color:#24292E;">() {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#6F42C1;">showDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    barrierDismissible</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">false</span><span style="color:#24292E;">, </span><span style="color:#6A737D;">//点击遮罩不关闭对话框</span></span>
<span class="line"><span style="color:#24292E;">    builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (context) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">        content</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Column</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          mainAxisSize</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">MainAxisSize</span><span style="color:#24292E;">.min,</span></span>
<span class="line"><span style="color:#24292E;">          children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">CircularProgressIndicator</span><span style="color:#24292E;">(),</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">Padding</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">              padding</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">EdgeInsets</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">only</span><span style="color:#24292E;">(top</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">26.0</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">              child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;正在加载，请稍后...&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            )</span></span>
<span class="line"><span style="color:#24292E;">          ],</span></span>
<span class="line"><span style="color:#24292E;">        ),</span></span>
<span class="line"><span style="color:#24292E;">      );</span></span>
<span class="line"><span style="color:#24292E;">    },</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>显示效果如图7-18所示：</p><p><img src="/assets/7-18.31695982.png" alt="图7-18"></p><p>如果我们嫌Loading框太宽，想自定义对话框宽度，这时只使用<code>SizedBox</code>或<code>ConstrainedBox</code>是不行的，原因是<code>showDialog</code>中已经给对话框设置了最小宽度约束，根据我们在第五章“尺寸限制类容器”一节中所述，我们可以使用<code>UnconstrainedBox</code>先抵消<code>showDialog</code>对宽度的约束，然后再使用<code>SizedBox</code>指定宽度，代码如下：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#E1E4E8;">... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#79B8FF;">UnconstrainedBox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">  constrainedAxis</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Axis</span><span style="color:#E1E4E8;">.vertical,</span></span>
<span class="line"><span style="color:#E1E4E8;">  child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">SizedBox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    width</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">280</span><span style="color:#E1E4E8;">,</span></span>
<span class="line"><span style="color:#E1E4E8;">    child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">AlertDialog</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">      content</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Column</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">        mainAxisSize</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">MainAxisSize</span><span style="color:#E1E4E8;">.min,</span></span>
<span class="line"><span style="color:#E1E4E8;">        children</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">&lt;</span><span style="color:#79B8FF;">Widget</span><span style="color:#F97583;">&gt;</span><span style="color:#E1E4E8;">[</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">CircularProgressIndicator</span><span style="color:#E1E4E8;">(value</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> .</span><span style="color:#79B8FF;">8</span><span style="color:#E1E4E8;">,),</span></span>
<span class="line"><span style="color:#E1E4E8;">          </span><span style="color:#79B8FF;">Padding</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            padding</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#F97583;">const</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">EdgeInsets</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">only</span><span style="color:#E1E4E8;">(top</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">26.0</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">            child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">Text</span><span style="color:#E1E4E8;">(</span><span style="color:#9ECBFF;">&quot;正在加载，请稍后...&quot;</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">          )</span></span>
<span class="line"><span style="color:#E1E4E8;">        ],</span></span>
<span class="line"><span style="color:#E1E4E8;">      ),</span></span>
<span class="line"><span style="color:#E1E4E8;">    ),</span></span>
<span class="line"><span style="color:#E1E4E8;">  ),</span></span>
<span class="line"><span style="color:#E1E4E8;">);</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#24292E;">... </span><span style="color:#6A737D;">//省略无关代码</span></span>
<span class="line"><span style="color:#005CC5;">UnconstrainedBox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">  constrainedAxis</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Axis</span><span style="color:#24292E;">.vertical,</span></span>
<span class="line"><span style="color:#24292E;">  child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">SizedBox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    width</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">280</span><span style="color:#24292E;">,</span></span>
<span class="line"><span style="color:#24292E;">    child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">AlertDialog</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">      content</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Column</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">        mainAxisSize</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">MainAxisSize</span><span style="color:#24292E;">.min,</span></span>
<span class="line"><span style="color:#24292E;">        children</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">&lt;</span><span style="color:#005CC5;">Widget</span><span style="color:#D73A49;">&gt;</span><span style="color:#24292E;">[</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">CircularProgressIndicator</span><span style="color:#24292E;">(value</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> .</span><span style="color:#005CC5;">8</span><span style="color:#24292E;">,),</span></span>
<span class="line"><span style="color:#24292E;">          </span><span style="color:#005CC5;">Padding</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            padding</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#D73A49;">const</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">EdgeInsets</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">only</span><span style="color:#24292E;">(top</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">26.0</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">            child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">Text</span><span style="color:#24292E;">(</span><span style="color:#032F62;">&quot;正在加载，请稍后...&quot;</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">          )</span></span>
<span class="line"><span style="color:#24292E;">        ],</span></span>
<span class="line"><span style="color:#24292E;">      ),</span></span>
<span class="line"><span style="color:#24292E;">    ),</span></span>
<span class="line"><span style="color:#24292E;">  ),</span></span>
<span class="line"><span style="color:#24292E;">);</span></span></code></pre></div><p>代码运行后，效果如图7-19所示：</p><p><img src="/assets/7-19.d47cdf63.png" alt="图7-19"></p><h3 id="_3-日历选择器" tabindex="-1">3. 日历选择器 <a class="header-anchor" href="#_3-日历选择器" aria-label="Permalink to &quot;3. 日历选择器&quot;">​</a></h3><p>我们先看一下Material风格的日历选择器，如图7-20所示：</p><p><img src="/assets/7-20.680b0494.png" alt="图7-20"></p><p>实现代码：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">DateTime</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">_showDatePicker1</span><span style="color:#E1E4E8;">() {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">var</span><span style="color:#E1E4E8;"> date </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">DateTime</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">now</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showDatePicker</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    initialDate</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> date,</span></span>
<span class="line"><span style="color:#E1E4E8;">    firstDate</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> date,</span></span>
<span class="line"><span style="color:#E1E4E8;">    lastDate</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> date.</span><span style="color:#B392F0;">add</span><span style="color:#E1E4E8;">( </span><span style="color:#6A737D;">//未来30天可选</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#79B8FF;">Duration</span><span style="color:#E1E4E8;">(days</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">30</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">    ),</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">DateTime</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">_showDatePicker1</span><span style="color:#24292E;">() {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">var</span><span style="color:#24292E;"> date </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">DateTime</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">now</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showDatePicker</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    initialDate</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> date,</span></span>
<span class="line"><span style="color:#24292E;">    firstDate</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> date,</span></span>
<span class="line"><span style="color:#24292E;">    lastDate</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> date.</span><span style="color:#6F42C1;">add</span><span style="color:#24292E;">( </span><span style="color:#6A737D;">//未来30天可选</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#005CC5;">Duration</span><span style="color:#24292E;">(days</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">30</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">    ),</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>iOS风格的日历选择器需要使用<code>showCupertinoModalPopup</code>方法和<code>CupertinoDatePicker</code>组件来实现：</p><div class="language-dart vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dart</span><pre class="shiki github-dark vp-code-dark"><code><span class="line"><span style="color:#79B8FF;">Future</span><span style="color:#E1E4E8;">&lt;</span><span style="color:#79B8FF;">DateTime</span><span style="color:#E1E4E8;">?&gt; </span><span style="color:#B392F0;">_showDatePicker2</span><span style="color:#E1E4E8;">() {</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">var</span><span style="color:#E1E4E8;"> date </span><span style="color:#F97583;">=</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">DateTime</span><span style="color:#E1E4E8;">.</span><span style="color:#B392F0;">now</span><span style="color:#E1E4E8;">();</span></span>
<span class="line"><span style="color:#E1E4E8;">  </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#B392F0;">showCupertinoModalPopup</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">    context</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> context,</span></span>
<span class="line"><span style="color:#E1E4E8;">    builder</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (ctx) {</span></span>
<span class="line"><span style="color:#E1E4E8;">      </span><span style="color:#F97583;">return</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">SizedBox</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">        height</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">200</span><span style="color:#E1E4E8;">,</span></span>
<span class="line"><span style="color:#E1E4E8;">        child</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">CupertinoDatePicker</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">          mode</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">CupertinoDatePickerMode</span><span style="color:#E1E4E8;">.dateAndTime,</span></span>
<span class="line"><span style="color:#E1E4E8;">          minimumDate</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> date,</span></span>
<span class="line"><span style="color:#E1E4E8;">          maximumDate</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> date.</span><span style="color:#B392F0;">add</span><span style="color:#E1E4E8;">(</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#79B8FF;">Duration</span><span style="color:#E1E4E8;">(days</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">30</span><span style="color:#E1E4E8;">),</span></span>
<span class="line"><span style="color:#E1E4E8;">          ),</span></span>
<span class="line"><span style="color:#E1E4E8;">          maximumYear</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> date.year </span><span style="color:#F97583;">+</span><span style="color:#E1E4E8;"> </span><span style="color:#79B8FF;">1</span><span style="color:#E1E4E8;">,</span></span>
<span class="line"><span style="color:#E1E4E8;">          onDateTimeChanged</span><span style="color:#F97583;">:</span><span style="color:#E1E4E8;"> (</span><span style="color:#79B8FF;">DateTime</span><span style="color:#E1E4E8;"> value) {</span></span>
<span class="line"><span style="color:#E1E4E8;">            </span><span style="color:#B392F0;">print</span><span style="color:#E1E4E8;">(value);</span></span>
<span class="line"><span style="color:#E1E4E8;">          },</span></span>
<span class="line"><span style="color:#E1E4E8;">        ),</span></span>
<span class="line"><span style="color:#E1E4E8;">      );</span></span>
<span class="line"><span style="color:#E1E4E8;">    },</span></span>
<span class="line"><span style="color:#E1E4E8;">  );</span></span>
<span class="line"><span style="color:#E1E4E8;">}</span></span></code></pre><pre class="shiki github-light vp-code-light"><code><span class="line"><span style="color:#005CC5;">Future</span><span style="color:#24292E;">&lt;</span><span style="color:#005CC5;">DateTime</span><span style="color:#24292E;">?&gt; </span><span style="color:#6F42C1;">_showDatePicker2</span><span style="color:#24292E;">() {</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">var</span><span style="color:#24292E;"> date </span><span style="color:#D73A49;">=</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">DateTime</span><span style="color:#24292E;">.</span><span style="color:#6F42C1;">now</span><span style="color:#24292E;">();</span></span>
<span class="line"><span style="color:#24292E;">  </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#6F42C1;">showCupertinoModalPopup</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">    context</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> context,</span></span>
<span class="line"><span style="color:#24292E;">    builder</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (ctx) {</span></span>
<span class="line"><span style="color:#24292E;">      </span><span style="color:#D73A49;">return</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">SizedBox</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">        height</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">200</span><span style="color:#24292E;">,</span></span>
<span class="line"><span style="color:#24292E;">        child</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">CupertinoDatePicker</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">          mode</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">CupertinoDatePickerMode</span><span style="color:#24292E;">.dateAndTime,</span></span>
<span class="line"><span style="color:#24292E;">          minimumDate</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> date,</span></span>
<span class="line"><span style="color:#24292E;">          maximumDate</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> date.</span><span style="color:#6F42C1;">add</span><span style="color:#24292E;">(</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#005CC5;">Duration</span><span style="color:#24292E;">(days</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">30</span><span style="color:#24292E;">),</span></span>
<span class="line"><span style="color:#24292E;">          ),</span></span>
<span class="line"><span style="color:#24292E;">          maximumYear</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> date.year </span><span style="color:#D73A49;">+</span><span style="color:#24292E;"> </span><span style="color:#005CC5;">1</span><span style="color:#24292E;">,</span></span>
<span class="line"><span style="color:#24292E;">          onDateTimeChanged</span><span style="color:#D73A49;">:</span><span style="color:#24292E;"> (</span><span style="color:#005CC5;">DateTime</span><span style="color:#24292E;"> value) {</span></span>
<span class="line"><span style="color:#24292E;">            </span><span style="color:#6F42C1;">print</span><span style="color:#24292E;">(value);</span></span>
<span class="line"><span style="color:#24292E;">          },</span></span>
<span class="line"><span style="color:#24292E;">        ),</span></span>
<span class="line"><span style="color:#24292E;">      );</span></span>
<span class="line"><span style="color:#24292E;">    },</span></span>
<span class="line"><span style="color:#24292E;">  );</span></span>
<span class="line"><span style="color:#24292E;">}</span></span></code></pre></div><p>运行效果如图7-21所示：</p><p><img src="/assets/7-21.6d83afa7.png" alt="图7-21"></p></div></div></main><footer class="VPDocFooter" data-v-6b87e69f data-v-ef5dee53><!--[--><!--]--><div class="edit-info" data-v-ef5dee53><div class="edit-link" data-v-ef5dee53><a class="VPLink link vp-external-link-icon no-icon edit-link-button" href="https://gitee.com/luoguangguang/note/tree/master/docs/largeFrontEnd/flutter/chapter7/dailog.md" target="_blank" rel="noreferrer" data-v-ef5dee53><!--[--><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="edit-link-icon" aria-label="edit icon" data-v-ef5dee53><path d="M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"></path><path d="M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"></path></svg> 在Gitee上参与编辑此页<!--]--></a></div><!----></div><nav class="prev-next" data-v-ef5dee53><div class="pager" data-v-ef5dee53><!----></div><div class="pager" data-v-ef5dee53><a class="pager-link next" href="./largeFrontEnd/flutter/chapter1/index.html" data-v-ef5dee53><span class="desc" data-v-ef5dee53>Next page</span><span class="title" data-v-ef5dee53>第一章 初识Flutter</span></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><footer class="VPFooter has-sidebar" data-v-1919c326 data-v-e03eb2e1><div class="container" data-v-e03eb2e1><p class="message" data-v-e03eb2e1>Released under the MIT License.</p><p class="copyright" data-v-e03eb2e1>Copyright © 2023-present LG of GZU</p></div></footer><!--[--><!--]--></div></div>
    <script>window.__VP_HASH_MAP__=JSON.parse("{\"backend_index.md\":\"0cb07c7c\",\"largefrontend_electron_index.md\":\"adab8e13\",\"largefrontend_flutter_chapter1_index.md\":\"5106cc23\",\"index.md\":\"20a66851\",\"largefrontend_flutter_chapter10_intro.md\":\"5756d1e8\",\"largefrontend_flutter_chapter10_index.md\":\"87e47f16\",\"largefrontend_flutter_chapter1_flutter_intro.md\":\"9ad5fc78\",\"largefrontend_flutter_chapter12_package_and_plugin.md\":\"c2f14cd7\",\"largefrontend_flutter_chapter12_flutter_web.md\":\"f4b6b743\",\"largefrontend_flutter_chapter10_combine.md\":\"333319d8\",\"largefrontend_flutter_chapter14_flutter_ui_system.md\":\"a1011f7b\",\"largefrontend_flutter_chapter11_index.md\":\"35dcdd7c\",\"largefrontend_flutter_chapter12_index.md\":\"890b799c\",\"largefrontend_flutter_chapter13_index.md\":\"6db9b579\",\"largefrontend_flutter_chapter14_index.md\":\"87f7da6b\",\"largefrontend_flutter_chapter1_mobile_development_intro.md\":\"40c15ac2\",\"largefrontend_flutter_chapter10_turn_box.md\":\"6a792fe1\",\"largefrontend_flutter_chapter3_index.md\":\"bc1d0de5\",\"largefrontend_flutter_chapter4_stack.md\":\"3f5c3186\",\"largefrontend_flutter_chapter1_install_flutter.md\":\"4543c368\",\"largefrontend_flutter_chapter14_paint.md\":\"8f7289b0\",\"largefrontend_flutter_chapter5_padding.md\":\"9fadce05\",\"largefrontend_flutter_chapter4_index.md\":\"f9b298f7\",\"largefrontend_flutter_chapter2_flutter_package_mgr.md\":\"4a3b7161\",\"largefrontend_flutter_chapter11_socket.md\":\"e8264e44\",\"largefrontend_flutter_chapter4_intro.md\":\"1341b5fd\",\"largefrontend_flutter_chapter14_update.md\":\"e4d2c2f0\",\"largefrontend_flutter_chapter5_index.md\":\"455baa0a\",\"largefrontend_flutter_chapter4_alignment.md\":\"a6596610\",\"largefrontend_flutter_chapter13_multi_languages_support.md\":\"c113238d\",\"largefrontend_flutter_chapter11_dio.md\":\"64f4e813\",\"largefrontend_flutter_chapter2_first_flutter_app.md\":\"b650181d\",\"largefrontend_flutter_chapter2_flutter_app_debug.md\":\"67a72433\",\"largefrontend_flutter_chapter2_state_manage.md\":\"9bb80d37\",\"largefrontend_flutter_chapter6_index.md\":\"5a321b81\",\"largefrontend_flutter_chapter5_material_scaffold.md\":\"8e6b896a\",\"largefrontend_flutter_chapter3_buttons.md\":\"ef950360\",\"largefrontend_flutter_chapter10_done_widget.md\":\"c3b44318\",\"largefrontend_flutter_chapter6_single_child_scrollview.md\":\"e3f75f3b\",\"largefrontend_flutter_chapter14_paint_flow.md\":\"d2f8102a\",\"largefrontend_flutter_chapter6_intro.md\":\"125a064e\",\"largefrontend_flutter_chapter5_transform.md\":\"22708e1e\",\"largefrontend_flutter_chapter14_layer.md\":\"4ed449fc\",\"largefrontend_flutter_chapter11_websocket.md\":\"0a022e47\",\"largefrontend_flutter_chapter5_fittedbox.md\":\"db915726\",\"largefrontend_flutter_chapter2_index.md\":\"d8e937b7\",\"largefrontend_flutter_chapter3_radio_and_checkbox.md\":\"025aba21\",\"largefrontend_flutter_chapter13_locallization_implement.md\":\"dc4b83fe\",\"largefrontend_flutter_chapter2_thread_model_and_error_report.md\":\"a29199d6\",\"largefrontend_flutter_chapter5_decoratedbox.md\":\"20f093ba\",\"largefrontend_flutter_chapter14_render_object.md\":\"55a1b551\",\"largefrontend_flutter_chapter14_element_buildcontext.md\":\"4272eae4\",\"largefrontend_flutter_chapter4_wrap_and_flow.md\":\"ac41b5bd\",\"largefrontend_flutter_chapter11_file_operation.md\":\"996a3a5d\",\"largefrontend_flutter_chapter13_faq.md\":\"ba7b9c70\",\"largefrontend_webfrontend_md_10.md\":\"51e0a312\",\"largefrontend_webfrontend_md_24.md\":\"0a4abd08\",\"largefrontend_flutter_chapter14_flutter_app_startup.md\":\"9b5942a1\",\"largefrontend_flutter_chapter10_custom_paint.md\":\"8b2a0a46\",\"largefrontend_flutter_chapter2_flutter_assets_mgr.md\":\"0e38b701\",\"largefrontend_interview_01.md\":\"2ac4b56d\",\"largefrontend_flutter_chapter8_index.md\":\"e83d3d80\",\"largefrontend_webfrontend_md_16.md\":\"a5610416\",\"largefrontend_flutter_chapter9_index.md\":\"3fb342a7\",\"largefrontend_flutter_chapter8_listener.md\":\"1b9b0316\",\"largefrontend_webfrontend_md_37.md\":\"3cacf3a2\",\"largefrontend_flutter_chapter4_layoutbuilder.md\":\"3d4bf94b\",\"largefrontend_webfrontend_md_17.md\":\"ee74edfb\",\"largefrontend_webfrontend_md_13.md\":\"b180bb5b\",\"largefrontend_flutter_chapter7_index.md\":\"0eb456b2\",\"largefrontend_webfrontend_md_31.md\":\"309453c7\",\"largefrontend_webfrontend_md_25.md\":\"95fdb4fe\",\"largefrontend_webfrontend_md_12.md\":\"3b14e491\",\"largefrontend_webfrontend_md_23.md\":\"18f08d72\",\"largefrontend_flutter_chapter11_json_model.md\":\"c84d2ccf\",\"largefrontend_webfrontend_md_01.md\":\"fbb7a35f\",\"largefrontend_flutter_chapter3_progress.md\":\"9bc148d3\",\"largefrontend_webfrontend_md_18.md\":\"ee651cc6\",\"largefrontend_flutter_sponsor.md\":\"e71431a9\",\"largefrontend_webfrontend_md_36.md\":\"f22f6d0d\",\"largefrontend_webfrontend_md_07.md\":\"71c2ad1d\",\"largefrontend_webfrontend_md_19.md\":\"e7907728\",\"largefrontend_webfrontend_md_20.md\":\"5a68bb4f\",\"largefrontend_webfrontend_md_32.md\":\"91d2f39f\",\"largefrontend_flutter_chapter7_futurebuilder_and_streambuilder.md\":\"af3535c0\",\"largefrontend_flutter_chapter9_hero.md\":\"25b46cf2\",\"largefrontend_flutter_chapter8_notification.md\":\"909f6756\",\"largefrontend_webfrontend_md_08.md\":\"0d59dce4\",\"largefrontend_flutter_chapter3_img_and_icon.md\":\"8b409b55\",\"largefrontend_webfrontend_md_04.md\":\"d6c15d55\",\"largefrontend_flutter_chapter9_animated_switcher.md\":\"9c0b3119\",\"largefrontend_webfrontend_md_22.md\":\"7d6fea68\",\"largefrontend_flutter_chapter2_flutter_widget_intro.md\":\"13414fea\",\"largefrontend_flutter_chapter13_intl.md\":\"d4776610\",\"largefrontend_overview_index.md\":\"3c87f69c\",\"largefrontend_flutter_chapter5_container.md\":\"373cc694\",\"largefrontend_wechatminiprogram_index.md\":\"7f40708d\",\"largefrontend_webfrontend_md_38.md\":\"3b6bb332\",\"linux_index.md\":\"624ecc66\",\"largefrontend_webfrontend_md_35.md\":\"f0538423\",\"myteam_index.md\":\"91a2c11f\",\"largefrontend_flutter_chapter6_pageview.md\":\"36fcbc65\",\"largefrontend_webfrontend_md_03.md\":\"2e5087f0\",\"largefrontend_webfrontend_md_21.md\":\"c181316e\",\"largefrontend_flutter_chapter3_input_and_form.md\":\"e4fba9dd\",\"largefrontend_flutter_chapter14_compositing.md\":\"6d96f932\",\"largefrontend_webfrontend_md_29.md\":\"c6fada7d\",\"largefrontend_flutter_chapter4_constraints.md\":\"9e4baace\",\"largefrontend_webfrontend_md_11.md\":\"63cd9c49\",\"largefrontend_webfrontend_md_14.md\":\"1423aeb1\",\"largefrontend_flutter_chapter6_tabview.md\":\"56048fb1\",\"largefrontend_webfrontend_md_33.md\":\"fdbe86fa\",\"largefrontend_flutter_chapter6_nestedscrollview.md\":\"2a66b86a\",\"largefrontend_webfrontend_md_34.md\":\"ad8ea220\",\"largefrontend_flutter_chapter2_flutter_router.md\":\"bb6e776c\",\"largefrontend_webfrontend_md_30.md\":\"cd2cb5aa\",\"largefrontend_flutter_chapter4_flex.md\":\"ebd43d6a\",\"largefrontend_webfrontend_md_09.md\":\"eedafcb1\",\"largefrontend_webfrontend_md_40.md\":\"4d4fefa1\",\"largefrontend_flutter_join_us.md\":\"44c81d86\",\"largefrontend_flutter_chapter9_route_transition.md\":\"f56cf837\",\"largefrontend_uniapp_index.md\":\"fa387c39\",\"largefrontend_flutter_chapter4_row_and_column.md\":\"964229f5\",\"largefrontend_flutter_chapter9_stagger_animation.md\":\"315538f5\",\"largefrontend_flutter_chapter3_text.md\":\"6720230c\",\"largefrontend_flutter_chapter10_watermark.md\":\"2e4ddf03\",\"largefrontend_flutter_chapter11_http.md\":\"efd2ee64\",\"largefrontend_webfrontend_md_06.md\":\"e20b049a\",\"largefrontend_flutter_summary.md\":\"2e31b0a8\",\"largefrontend_flutter_chapter6_animatedlist.md\":\"20d9436f\",\"largefrontend_flutter_chapter5_clip.md\":\"91f4174c\",\"largefrontend_webfrontend_md_02.md\":\"40cd2099\",\"largefrontend_flutter_chapter6_gridview.md\":\"b3be7e60\",\"largefrontend_flutter_chapter6_custom_scrollview.md\":\"01be950c\",\"largefrontend_flutter_chapter11_download_with_chunks.md\":\"9379cc89\",\"largefrontend_flutter_chapter6_scroll_controller.md\":\"ffa2d5fd\",\"largefrontend_flutter_chapter9_intro.md\":\"3fc29b5f\",\"largefrontend_flutter_chapter1_dart.md\":\"6bba4e7c\",\"largefrontend_flutter_chapter7_inherited_widget.md\":\"5a21d704\",\"largefrontend_flutter_index.md\":\"cd81fbbe\",\"largefrontend_flutter_reference.md\":\"36336375\",\"largefrontend_flutter_chapter6_keepalive.md\":\"535137be\",\"largefrontend_flutter_chapter14_layout.md\":\"0d7a8df3\",\"largefrontend_flutter_chapter6_sliver.md\":\"0c8b7553\",\"largefrontend_webfrontend_md_39.md\":\"aef49a57\",\"largefrontend_webfrontend_md_15.md\":\"bf9ff1a1\",\"largefrontend_flutter_chapter14_image_and_cache.md\":\"9622c56b\",\"largefrontend_webfrontend_md_28.md\":\"83169d10\",\"largefrontend_flutter_chapter8_eventbus.md\":\"fc0db86d\",\"largefrontend_flutter_chapter7_value_listenable_builder.md\":\"a0c76121\",\"largefrontend_flutter_preface.md\":\"604b9934\",\"largefrontend_flutter_chapter7_theme.md\":\"c21036bc\",\"largefrontend_webfrontend_md_05.md\":\"f7607009\",\"largefrontend_flutter_chapter6_listview.md\":\"472910bd\",\"largefrontend_flutter_chapter7_provider.md\":\"ab590744\",\"largefrontend_flutter_chapter8_gesture.md\":\"859bbb38\",\"largefrontend_flutter_chapter9_animated_widgets.md\":\"e8cd3c4d\",\"largefrontend_webfrontend_md_26.md\":\"4928006b\",\"largefrontend_flutter_chapter10_gradient_circular_progress_demo.md\":\"b3d48a2c\",\"largefrontend_flutter_chapter8_hittest.md\":\"e963812b\",\"largefrontend_flutter_chapter7_willpopscope.md\":\"d224ecce\",\"largefrontend_flutter_chapter9_animation_structure.md\":\"672eb3c0\",\"largefrontend_flutter_chapter8_gesture_conflict.md\":\"15bbadba\",\"largefrontend_webfrontend_md_27.md\":\"0b5b5e39\",\"largefrontend_flutter_chapter7_dailog.md\":\"5f91e51a\",\"largefrontend_flutter_chapter10_custom_checkbox.md\":\"0db7d50f\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"zh-CN\",\"dir\":\"ltr\",\"title\":\"落光的Pro博客\",\"description\":\"Vite & Vue powered static site generator.\",\"base\":\"./\",\"head\":[],\"appearance\":true,\"themeConfig\":{\"search\":{\"provider\":\"local\",\"options\":{\"locales\":{\"zh\":{\"translations\":{\"button\":{\"buttonText\":\"搜索文档\",\"buttonAriaLabel\":\"搜索文档\"},\"modal\":{\"noResultsText\":\"无法找到相关结果\",\"resetButtonTitle\":\"清除查询条件\",\"footer\":{\"selectText\":\"选择\",\"navigateText\":\"切换\"}}}}}}},\"logo\":\"/icon-radius.png\",\"nav\":[{\"text\":\"大前端\",\"items\":[{\"text\":\"Web前端\",\"link\":\"/largeFrontEnd/webFrontEnd/md/01.md\"},{\"text\":\"Uni-app\",\"link\":\"/largeFrontEnd/uniapp/\"},{\"text\":\"微信小程序\",\"link\":\"/largeFrontEnd/weChatMiniProgram/\"},{\"text\":\"Electron\",\"link\":\"/largeFrontEnd/electron/\"},{\"text\":\"Flutter\",\"link\":\"/largeFrontEnd/flutter/\"},{\"text\":\"前端面试题\",\"link\":\"/largeFrontEnd/interview/01.md\"}]},{\"text\":\"后端\",\"link\":\"/backEnd/\"},{\"text\":\"Linux\",\"link\":\"/linux/\"},{\"text\":\"我的团队\",\"link\":\"/myTeam/\"}],\"sidebar\":{\"/largeFrontEnd/webFrontEnd/\":[{\"text\":\"第一阶段  基础入门\",\"collapsed\":true,\"items\":[{\"text\":\"一、基础认知\",\"link\":\"/largeFrontEnd/webFrontEnd/md/01.md\"},{\"text\":\"二、HTML标签学习\",\"link\":\"/largeFrontEnd/webFrontEnd/md/02.md\"},{\"text\":\"三、HTML基础\",\"link\":\"/largeFrontEnd/webFrontEnd/md/03.md\"},{\"text\":\"四、CSS基础\",\"link\":\"/largeFrontEnd/webFrontEnd/md/04.md\"},{\"text\":\"五、CSS进阶\",\"link\":\"/largeFrontEnd/webFrontEnd/md/05.md\"},{\"text\":\"六、盒子模型\",\"link\":\"/largeFrontEnd/webFrontEnd/md/06.md\"},{\"text\":\"七、CSS浮动\",\"link\":\"/largeFrontEnd/webFrontEnd/md/07.md\"},{\"text\":\"八、CSS定位装饰\",\"link\":\"/largeFrontEnd/webFrontEnd/md/08.md\"},{\"text\":\"九、CSS精灵图\",\"link\":\"/largeFrontEnd/webFrontEnd/md/09.md\"},{\"text\":\"项目前置认知\",\"link\":\"/largeFrontEnd/webFrontEnd/md/10.md\"},{\"text\":\"项目结构搭建\",\"link\":\"/largeFrontEnd/webFrontEnd/md/11.md\"},{\"text\":\"字体图标、动画\",\"link\":\"/largeFrontEnd/webFrontEnd/md/12.md\"},{\"text\":\"移动web开发\",\"link\":\"/largeFrontEnd/webFrontEnd/md/13.md\"}]},{\"text\":\"第二阶段 技术进阶\",\"collapsed\":true,\"items\":[{\"text\":\"JavaScript深入浅出\",\"link\":\"/largeFrontEnd/webFrontEnd/md/14.md\"},{\"text\":\"JavaScript核心之web APIs\",\"link\":\"/largeFrontEnd/webFrontEnd/md/15.md\"},{\"text\":\"一、Web APIS导读\",\"link\":\"/largeFrontEnd/webFrontEnd/md/16.md\"},{\"text\":\"二、DOM导读\",\"link\":\"/largeFrontEnd/webFrontEnd/md/17.md\"},{\"text\":\"三、事件高级导读\",\"link\":\"/largeFrontEnd/webFrontEnd/md/18.md\"},{\"text\":\"四、BOM导读\",\"link\":\"/largeFrontEnd/webFrontEnd/md/19.md\"},{\"text\":\"五、PC网页特效导读\",\"link\":\"/largeFrontEnd/webFrontEnd/md/20.md\"},{\"text\":\"六、移动端特效导读\",\"link\":\"/largeFrontEnd/webFrontEnd/md/21.md\"},{\"text\":\"七、本地存储导读\",\"link\":\"/largeFrontEnd/webFrontEnd/md/22.md\"},{\"text\":\"jQuery入门导读\",\"link\":\"/largeFrontEnd/webFrontEnd/md/23.md\"},{\"text\":\"数据可视化项目导读\",\"link\":\"/largeFrontEnd/webFrontEnd/md/24.md\"}]},{\"text\":\"Node.js\",\"collapsed\":true,\"items\":[{\"text\":\"buffer(缓冲器)\",\"link\":\"/largeFrontEnd/webFrontEnd/md/25.md\"},{\"text\":\"计算机基础\",\"link\":\"/largeFrontEnd/webFrontEnd/md/26.md\"},{\"text\":\"fs模块\",\"link\":\"/largeFrontEnd/webFrontEnd/md/27.md\"},{\"text\":\"path模块\",\"link\":\"/largeFrontEnd/webFrontEnd/md/28.md\"},{\"text\":\"HTTP模块\",\"link\":\"/largeFrontEnd/webFrontEnd/md/29.md\"},{\"text\":\"Express框架\",\"link\":\"/largeFrontEnd/webFrontEnd/md/30.md\"},{\"text\":\"Mongodb\",\"link\":\"/largeFrontEnd/webFrontEnd/md/31.md\"}]},{\"text\":\"Ajax\",\"link\":\"/largeFrontEnd/webFrontEnd/md/32.md\"},{\"text\":\"前端面试题\",\"collapsed\":true,\"items\":[{\"text\":\"一、CSS\",\"link\":\"/largeFrontEnd/webFrontEnd/md/33.md\"},{\"text\":\"二、JavaScript\",\"link\":\"/largeFrontEnd/webFrontEnd/md/34.md\"},{\"text\":\"三、HTML5CSS3\",\"link\":\"/largeFrontEnd/webFrontEnd/md/35.md\"},{\"text\":\"四、Vue\",\"link\":\"/largeFrontEnd/webFrontEnd/md/36.md\"},{\"text\":\"五、Echarts\",\"link\":\"/largeFrontEnd/webFrontEnd/md/37.md\"},{\"text\":\"六.Uni-APP\",\"link\":\"/largeFrontEnd/webFrontEnd/md/38.md\"},{\"text\":\"七、webpack\",\"link\":\"/largeFrontEnd/webFrontEnd/md/39.md\"},{\"text\":\"八、Git\",\"link\":\"/largeFrontEnd/webFrontEnd/md/40.md\"}]}],\"/largeFrontEnd/flutter/\":[{\"text\":\"Flutter入门到实战\",\"collapsed\":false,\"items\":[{\"text\":\"第一章 初识Flutter\",\"link\":\"/largeFrontEnd/flutter/chapter1/index.md\"},{\"text\":\"第二章 简介\",\"link\":\"/largeFrontEnd/flutter/chapter2/index.md\"},{\"text\":\"第三章 基础组件\",\"link\":\"/largeFrontEnd/flutter/chapter3/index.md\"},{\"text\":\"第四章 布局类组件\",\"link\":\"/largeFrontEnd/flutter/chapter4/index.md\"},{\"text\":\"第五章 容器类Widget\",\"link\":\"/largeFrontEnd/flutter/chapter5/index.md\"},{\"text\":\"第六章 可滚动组件\",\"link\":\"/largeFrontEnd/flutter/chapter6/index.md\"},{\"text\":\"第七章 功能型Widget简介\",\"link\":\"/largeFrontEnd/flutter/chapter7/index.md\"},{\"text\":\"第八章 事件处理与通知\",\"link\":\"/largeFrontEnd/flutter/chapter8/index.md\"},{\"text\":\"第九章 动画\",\"link\":\"/largeFrontEnd/flutter/chapter9/index.md\"},{\"text\":\"第十章 自定义组件\",\"link\":\"/largeFrontEnd/flutter/chapter10/index.md\"},{\"text\":\"第十一章 文件操作\",\"link\":\"/largeFrontEnd/flutter/chapter11/index.md\"},{\"text\":\"第十二章 Flutter 扩展\",\"link\":\"/largeFrontEnd/flutter/chapter12/index.md\"},{\"text\":\"第十三章 多语言\",\"link\":\"/largeFrontEnd/flutter/chapter13/index.md\"},{\"text\":\"第十四章 高级进阶\",\"link\":\"/largeFrontEnd/flutter/chapter14/index.md\"}]}]},\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://gitee.com/luoguangguang\"},{\"icon\":{\"svg\":\"<svg role=\\\"img\\\" viewBox=\\\"0 0 24 24\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><title>Dribbble</title><path d=\\\"M12...6.38z\\\"/></svg>\"},\"link\":\"...\",\"ariaLabel\":\"cool link\"}],\"footer\":{\"message\":\"Released under the MIT License.\",\"copyright\":\"Copyright © 2023-present LG of GZU\"},\"editLink\":{\"pattern\":\"https://gitee.com/luoguangguang/note/tree/master/docs/:path\",\"text\":\"在Gitee上参与编辑此页\"},\"carbonAds\":{\"code\":\"your-carbon-code\",\"placement\":\"your-carbon-placement\"}},\"locales\":{},\"scrollOffset\":90,\"cleanUrls\":false}");</script>
    
  </body>
</html>